diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index 032c0e73bbd..1a73fe0e564 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -973,6 +973,54 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) if v_guid == obj_guid: match_count += 1 if match_count != 1: + reverse_syntax_oid = self.samdb_schema.get_syntax_oid_from_lDAPDisplayName(reverse_link_name) + if syntax_oid == dsdb.DSDB_SYNTAX_BINARY_DN or reverse_syntax_oid == dsdb.DSDB_SYNTAX_BINARY_DN: + if not linkID & 1: + # Forward binary multi-valued linked attribute + forward_count = 0 + for w in obj[attrname]: + w_guid = dsdb_Dn(self.samdb, w).dn.get_extended_component("GUID") + if w_guid == guid: + forward_count += 1 + + if match_count == forward_count: + continue + + error_count += 1 + + # Add or remove the missing number of backlinks + diff_count = forward_count - match_count + + # Loop until the difference between the forward and + # the backward links is resolved. + while diff_count != 0: + if diff_count > 0: + # self.err_missing_backlink(obj, attrname, + # obj.dn.extended_str(), + # reverse_link_name, + # dsdb_dn.dn) + # diff_count -= 1 + # TODO no method to fix these right now + self.report("ERROR: Can't fix missing " + "multi-valued backlinks on %s" % str(dsdb_dn.dn)) + break + else: + self.err_orphaned_backlink(res[0], reverse_link_name, + obj.dn.extended_str(), attrname, + dsdb_dn.dn) + diff_count += 1 + + else: + # If there's a backward link on binary multi-valued linked attribute, + # let the check on the forward link remedy the value. + # UNLESS, there is no forward link detected. + if match_count == 0: + self.err_orphaned_backlink(obj, attrname, + val, reverse_link_name, + dsdb_dn.dn) + + continue + error_count += 1 if linkID & 1: # Backlink exists, but forward link does not diff --git a/selftest/knownfail b/selftest/knownfail index 7c5417b6bc1..cfd4b359a5e 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -315,3 +315,5 @@ ^samba3.smb2.credits.session_setup_credits_granted.* ^samba3.smb2.credits.single_req_credits_granted.* ^samba3.smb2.credits.skipped_mid.* +^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_dbcheck +^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_missing diff --git a/source4/selftest/provisions/release-4-5-0-pre1/add-dangling-multi-backlink.ldif b/source4/selftest/provisions/release-4-5-0-pre1/add-dangling-multi-backlink.ldif new file mode 100644 index 00000000000..f62877e4d37 --- /dev/null +++ b/source4/selftest/provisions/release-4-5-0-pre1/add-dangling-multi-backlink.ldif @@ -0,0 +1,10 @@ +dn: CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp +changetype: modify +delete: msDS-RevealedUsers +msDS-RevealedUsers: B:96:3700090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:;;CN=Administrator,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5A00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:;;CN=Administrator,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp + +dn: CN=dangling-multi5,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +changetype: modify +add: msDS-RevealedDSAs +msDS-RevealedDSAs: ;;CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp diff --git a/source4/selftest/provisions/release-4-5-0-pre1/add-dangling-multilink-users.ldif b/source4/selftest/provisions/release-4-5-0-pre1/add-dangling-multilink-users.ldif new file mode 100644 index 00000000000..bb40087e89f --- /dev/null +++ b/source4/selftest/provisions/release-4-5-0-pre1/add-dangling-multilink-users.ldif @@ -0,0 +1,20 @@ +dn: CN=dangling-multi1,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp +objectclass: user +samaccountname: dangling-multi1 + +dn: CN=dangling-multi2,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp +objectclass: user +samaccountname: dangling-multi2 + +dn: CN=dangling-multi3,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp +objectclass: user +samaccountname: dangling-multi3 + +dn: CN=dangling-multi4,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp +objectclass: user +samaccountname: dangling-multi4 + +dn: CN=dangling-multi5,CN=users,DC=release-4-5-0-pre1,DC=samba,DC=corp +objectclass: user +samaccountname: dangling-multi5 + diff --git a/source4/selftest/provisions/release-4-5-0-pre1/add-initially-normal-multilink.ldif b/source4/selftest/provisions/release-4-5-0-pre1/add-initially-normal-multilink.ldif new file mode 100644 index 00000000000..6633e61257c --- /dev/null +++ b/source4/selftest/provisions/release-4-5-0-pre1/add-initially-normal-multilink.ldif @@ -0,0 +1,19 @@ +dn: CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp +changetype: modify +add: msDS-RevealedUsers +msDS-RevealedUsers: B:96:3700090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi1,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:3700090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi2,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:3700090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi3,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:3700090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=Administrator,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5A00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi1,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5A00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi2,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5A00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi3,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5A00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=Administrator,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5E00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi1,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5E00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi2,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5E00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi3,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:5E00090002000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=Administrator,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:7D00090001000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi1,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:7D00090001000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi2,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:7D00090001000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=dangling-multi3,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedUsers: B:96:7D00090001000000E078C90E0300000097016C30ACF34E469BDF57F1E468694CA10E000000000000A10E000000000000:CN=Administrator,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp diff --git a/source4/selftest/provisions/release-4-5-0-pre1/delete-only-multi-backlink.ldif b/source4/selftest/provisions/release-4-5-0-pre1/delete-only-multi-backlink.ldif new file mode 100644 index 00000000000..1890b5788a4 --- /dev/null +++ b/source4/selftest/provisions/release-4-5-0-pre1/delete-only-multi-backlink.ldif @@ -0,0 +1,13 @@ +dn: CN=dangling-multi2,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +changetype: modify +delete: msDS-RevealedDSAs +msDS-RevealedDSAs: ;;CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedDSAs: ;;CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedDSAs: ;;CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedDSAs: ;;CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp + +dn: CN=dangling-multi3,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp +changetype: modify +delete: msDS-RevealedDSAs +msDS-RevealedDSAs: ;;CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp +msDS-RevealedDSAs: ;;CN=DOUGLASB-DESKTO,OU=Domain Controllers,DC=release-4-5-0-pre1,DC=samba,DC=corp diff --git a/testprogs/blackbox/dbcheck-links.sh b/testprogs/blackbox/dbcheck-links.sh index 2a1bfbace02..9376e2a59bf 100755 --- a/testprogs/blackbox/dbcheck-links.sh +++ b/testprogs/blackbox/dbcheck-links.sh @@ -200,6 +200,78 @@ dangling_one_way() { fi } +dangling_multi_valued() { + # multi1 - All 4 backlinks + # multi2 - Missing all 4 backlinks + # multi3 - Missing 2 backlinks + # Administrator - Has 2 too many backlinks + # multi5 - Has 2 backlinks but no forward links + ldif=$release_dir/add-dangling-multilink-users.ldif + TZ=UTC $ldbadd -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif + if [ "$?" != "0" ]; then + return 1 + fi + + ldif=$release_dir/add-initially-normal-multilink.ldif + TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif + if [ "$?" != "0" ]; then + return 1 + fi + + ldif=$release_dir/delete-only-multi-backlink.ldif + TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb.d/DC%3DRELEASE-4-5-0-PRE1,DC%3DSAMBA,DC%3DCORP.ldb $ldif + if [ "$?" != "0" ]; then + return 1 + fi + + ldif=$release_dir/add-dangling-multi-backlink.ldif + TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb.d/DC%3DRELEASE-4-5-0-PRE1,DC%3DSAMBA,DC%3DCORP.ldb $ldif + if [ "$?" != "0" ]; then + return 1 + fi + + $PYTHON $BINDIR/samba-tool dbcheck -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --fix --yes + if [ "$?" != "1" ]; then + return 1 + fi +} + +dangling_multi_valued_check_missing() { + WORDS=`TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb '(samaccountname=dangling-multi2)' -s sub -b DC=release-4-5-0-pre1,DC=samba,DC=corp --show-deleted --reveal --sorted msDS-RevealedDSAs | grep msDS-RevealedDSAs | wc -l` + if [ $WORDS -ne 4 ]; then + echo Got only $WORDS links for dangling-multi2 + return 1 + fi + WORDS=`TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb '(samaccountname=dangling-multi3)' -s sub -b DC=release-4-5-0-pre1,DC=samba,DC=corp --show-deleted --reveal --sorted msDS-RevealedDSAs | grep msDS-RevealedDSAs | wc -l` + if [ $WORDS -ne 4 ]; then + echo Got only $WORDS links for dangling-multi3 + return 1 + fi +} + +dangling_multi_valued_check_equal_or_too_many() { + WORDS=`TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb '(samaccountname=dangling-multi1)' -s sub -b DC=release-4-5-0-pre1,DC=samba,DC=corp --show-deleted --reveal --sorted msDS-RevealedDSAs | grep msDS-RevealedDSAs | wc -l` + if [ $WORDS -ne 4 ]; then + echo Got $WORDS links for dangling-multi1 + return 1 + fi + + WORDS=`TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb '(samaccountname=dangling-multi5)' -s sub -b DC=release-4-5-0-pre1,DC=samba,DC=corp --show-deleted --reveal --sorted msDS-RevealedDSAs | grep msDS-RevealedDSAs | wc -l` + + if [ $WORDS -ne 0 ]; then + echo Got $WORDS links for dangling-multi5 + return 1 + fi + + WORDS=`TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb '(samaccountname=Administrator)' -s sub -b DC=release-4-5-0-pre1,DC=samba,DC=corp --show-deleted --reveal --sorted msDS-RevealedDSAs | grep msDS-RevealedDSAs | wc -l` + + if [ $WORDS -ne 2 ]; then + echo Got $WORDS links for Administrator + return 1 + fi +} + + if [ -d $release_dir ]; then testit $RELEASE undump testit "add_two_more_users" add_two_more_users @@ -216,6 +288,11 @@ if [ -d $release_dir ]; then testit "check_expected_after_objects" check_expected_after_objects testit "dangling_one_way" dangling_one_way testit "dbcheck_clean" dbcheck_clean + testit "dangling_multi_valued" dangling_multi_valued + testit "dangling_multi_valued_check_missing" dangling_multi_valued_check_missing + testit "dangling_multi_valued_check_equal_or_too_many" dangling_multi_valued_check_equal_or_too_many + # Currently this cannot pass + testit "dangling_multi_valued_dbcheck" dbcheck_clean else subunit_start_test $RELEASE subunit_skip_test $RELEASE <