mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
dbcheck: Check for and remove duplicate values in attributes
This can happen with three DCs and custom schema, but we test it by just forcing the values directly into the backing tdb. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
This commit is contained in:
parent
13e62b2e35
commit
c79c1e405d
@ -49,6 +49,7 @@ class dbcheck(object):
|
||||
self.remove_all_unknown_attributes = False
|
||||
self.remove_all_empty_attributes = False
|
||||
self.fix_all_normalisation = False
|
||||
self.fix_all_duplicates = False
|
||||
self.fix_all_DN_GUIDs = False
|
||||
self.fix_all_binary_dn = False
|
||||
self.remove_all_deleted_DN_links = False
|
||||
@ -292,6 +293,23 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
|
||||
validate=False):
|
||||
self.report("Normalised attribute %s" % attrname)
|
||||
|
||||
def err_duplicate_values(self, dn, attrname, dup_values, values):
|
||||
'''fix attribute normalisation errors'''
|
||||
self.report("ERROR: Duplicate values for attribute '%s' in '%s'" % (attrname, dn))
|
||||
self.report("Values contain a duplicate: [%s]/[%s]!" % (','.join(dup_values), ','.join(values)))
|
||||
if not self.confirm_all("Fix duplicates for '%s' from '%s'?" % (attrname, dn), 'fix_all_duplicates'):
|
||||
self.report("Not fixing attribute '%s'" % attrname)
|
||||
return
|
||||
|
||||
m = ldb.Message()
|
||||
m.dn = dn
|
||||
m[attrname] = ldb.MessageElement(values, ldb.FLAG_MOD_REPLACE, attrname)
|
||||
|
||||
if self.do_modify(m, ["relax:0", "show_recycled:1"],
|
||||
"Failed to remove duplicate value on attribute %s" % attrname,
|
||||
validate=False):
|
||||
self.report("Removed duplicate value on attribute %s" % attrname)
|
||||
|
||||
def is_deleted_objects_dn(self, dsdb_dn):
|
||||
'''see if a dsdb_Dn is the special Deleted Objects DN'''
|
||||
return dsdb_dn.prefix == "B:32:%s:" % dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER
|
||||
@ -1447,14 +1465,22 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
|
||||
# it's some form of DN, do specialised checking on those
|
||||
error_count += self.check_dn(obj, attrname, syntax_oid)
|
||||
|
||||
values = set()
|
||||
# check for incorrectly normalised attributes
|
||||
for val in obj[attrname]:
|
||||
values.add(str(val))
|
||||
|
||||
normalised = self.samdb.dsdb_normalise_attributes(self.samdb_schema, attrname, [val])
|
||||
if len(normalised) != 1 or normalised[0] != val:
|
||||
self.err_normalise_mismatch(dn, attrname, obj[attrname])
|
||||
error_count += 1
|
||||
break
|
||||
|
||||
if len(obj[attrname]) != len(values):
|
||||
self.err_duplicate_values(dn, attrname, obj[attrname], list(values))
|
||||
error_count += 1
|
||||
break
|
||||
|
||||
if str(attrname).lower() == "instancetype":
|
||||
calculated_instancetype = self.calculate_instancetype(dn)
|
||||
if len(obj["instanceType"]) != 1 or obj["instanceType"][0] != str(calculated_instancetype):
|
||||
|
@ -0,0 +1,9 @@
|
||||
|
||||
# 0 referrals
|
||||
# 1 entries
|
||||
dn: CN=Administrator,CN=Users,DC=release-4-1-0rc3,DC=samba,DC=corp
|
||||
otherHomePhone: 1
|
||||
otherHomePhone: 2
|
||||
otherHomePhone: 3
|
||||
# record 1
|
||||
# returned 1 records
|
@ -0,0 +1,9 @@
|
||||
dn: cn=administrator,cn=users,dc=release-4-1-0rc3,dc=samba,dc=corp
|
||||
changetype: modify
|
||||
add: otherHomePhone
|
||||
otherHomePhone: 1
|
||||
otherHomePhone: 2
|
||||
otherHomePhone: 1
|
||||
otherHomePhone: 3
|
||||
otherHomePhone: 2
|
||||
-
|
@ -207,6 +207,39 @@ check_expected_after_values() {
|
||||
return 0
|
||||
}
|
||||
|
||||
check_forced_duplicate_values() {
|
||||
if [ x$RELEASE = x"release-4-1-0rc3" ]; then
|
||||
ldif=$release_dir/forced-duplicate-value-for-dbcheck.ldif
|
||||
TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb.d/DC%3DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb $ldif
|
||||
if [ "$?" != "0" ]; then
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# This should 'fail', because it returns the number of modified records
|
||||
dbcheck_after_dup() {
|
||||
if [ x$RELEASE = x"release-4-1-0rc3" ]; then
|
||||
$PYTHON $BINDIR/samba-tool dbcheck --cross-ncs --fix --yes -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $@
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_expected_after_dup_values() {
|
||||
if [ x$RELEASE = x"release-4-1-0rc3" ]; then
|
||||
tmpldif=$PREFIX_ABS/$RELEASE/expected-otherphone-after-dbcheck.ldif.tmp
|
||||
TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb cn=administrator -s base -b cn=administrator,cn=users,DC=release-4-1-0rc3,DC=samba,DC=corp otherHomePhone --sorted --show-binary | sort > $tmpldif
|
||||
diff $tmpldif $release_dir/expected-otherphone-after-dbcheck.ldif
|
||||
if [ "$?" != "0" ]; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# But having fixed it all up, this should pass
|
||||
dbcheck_clean() {
|
||||
$PYTHON $BINDIR/samba-tool dbcheck --cross-ncs -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $@
|
||||
@ -269,6 +302,9 @@ if [ -d $release_dir ]; then
|
||||
testit "check_expected_before_values" check_expected_before_values
|
||||
testit_expect_failure "dbcheck" dbcheck
|
||||
testit "check_expected_after_values" check_expected_after_values
|
||||
testit "check_forced_duplicate_values" check_forced_duplicate_values
|
||||
testit_expect_failure "dbcheck_after_dup" dbcheck_after_dup
|
||||
testit "check_expected_after_dup_values" check_expected_after_dup_values
|
||||
testit "dbcheck_clean" dbcheck_clean
|
||||
testit_expect_failure "dbcheck_acl_reset" dbcheck_acl_reset
|
||||
testit "dbcheck_acl_reset_clean" dbcheck_acl_reset_clean
|
||||
|
Loading…
Reference in New Issue
Block a user