summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/samba/dbchecker.py19
-rw-r--r--source4/dsdb/pydsdb.c1
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c64
-rw-r--r--source4/dsdb/samdb/samdb.h3
-rw-r--r--source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif19
-rw-r--r--source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt5
-rwxr-xr-xtestprogs/blackbox/dbcheck-links.sh65
7 files changed, 171 insertions, 5 deletions
diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index 00194afffaf..c64fd4c1159 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -656,7 +656,8 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
m.dn = dn
m['old_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname)
m['new_value'] = ldb.MessageElement(str(dsdb_dn), ldb.FLAG_MOD_ADD, attrname)
- if self.do_modify(m, ["show_recycled:1"],
+ if self.do_modify(m, ["show_recycled:1",
+ "local_oid:%s:1" % dsdb.DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME],
"Failed to fix old DN string on attribute %s" % (attrname)):
self.report("Fixed old DN string on attribute %s" % (attrname))
@@ -1298,14 +1299,22 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
res[0].dn, "SID")
continue
+ # Only for non-links, not even forward-only links
+ # (otherwise this breaks repl_meta_data):
+ #
# Now we have checked the GUID and SID, offer to fix old
- # DN strings as a non-error (for forward links with no
+ # DN strings as a non-error (DNs, not links so no
# backlink). Samba does not maintain this string
# otherwise, so we don't increment error_count.
if reverse_link_name is None:
- if str(res[0].dn) != str(dsdb_dn.dn):
- self.err_dn_string_component_old(obj.dn, attrname, val, dsdb_dn,
- res[0].dn)
+ if linkID == 0 and str(res[0].dn) != str(dsdb_dn.dn):
+ # Pass in the old/bad DN without the <GUID=...> part,
+ # otherwise the LDB code will correct it on the way through
+ # (Note: we still want to preserve the DSDB DN prefix in the
+ # case of binary DNs)
+ bad_dn = dsdb_dn.prefix + dsdb_dn.dn.get_linearized()
+ self.err_dn_string_component_old(obj.dn, attrname, bad_dn,
+ dsdb_dn, res[0].dn)
continue
# check the reverse_link is correct if there should be one
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index d10c7ec3b9d..a25f3411ae7 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1582,6 +1582,7 @@ MODULE_INIT_FUNC(dsdb)
ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
+ ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 7395f52524e..c4a41a28d04 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -3333,6 +3333,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
const struct ldb_message_element *guid_el = NULL;
struct ldb_control *sd_propagation_control;
struct ldb_control *fix_links_control = NULL;
+ struct ldb_control *fix_dn_name_control = NULL;
struct replmd_private *replmd_private =
talloc_get_type(ldb_module_get_private(module), struct replmd_private);
@@ -3391,6 +3392,69 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
+ fix_dn_name_control = ldb_request_get_control(req,
+ DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
+ if (fix_dn_name_control != NULL) {
+ struct dsdb_schema *schema = NULL;
+ const struct dsdb_attribute *sa = NULL;
+
+ if (req->op.mod.message->num_elements != 2) {
+ return ldb_module_operr(module);
+ }
+
+ if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_DELETE) {
+ return ldb_module_operr(module);
+ }
+
+ if (req->op.mod.message->elements[1].flags != LDB_FLAG_MOD_ADD) {
+ return ldb_module_operr(module);
+ }
+
+ if (req->op.mod.message->elements[0].num_values != 1) {
+ return ldb_module_operr(module);
+ }
+
+ if (req->op.mod.message->elements[1].num_values != 1) {
+ return ldb_module_operr(module);
+ }
+
+ schema = dsdb_get_schema(ldb, req);
+ if (schema == NULL) {
+ return ldb_module_operr(module);
+ }
+
+ if (ldb_attr_cmp(req->op.mod.message->elements[0].name,
+ req->op.mod.message->elements[1].name) != 0) {
+ return ldb_module_operr(module);
+ }
+
+ sa = dsdb_attribute_by_lDAPDisplayName(schema,
+ req->op.mod.message->elements[0].name);
+ if (sa == NULL) {
+ return ldb_module_operr(module);
+ }
+
+ if (sa->dn_format == DSDB_INVALID_DN) {
+ return ldb_module_operr(module);
+ }
+
+ if (sa->linkID != 0) {
+ return ldb_module_operr(module);
+ }
+
+ /*
+ * If we are run from dbcheck and we are not updating
+ * a link (as these would need to be sorted and so
+ * can't go via such a simple update, then do not
+ * trigger replicated updates and a new USN from this
+ * change, it wasn't a real change, just a new
+ * (correct) string DN
+ */
+
+ fix_dn_name_control->critical = false;
+ return ldb_next_request(module, req);
+ }
+
ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
guid_el = ldb_msg_find_element(req->op.mod.message, "objectGUID");
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index 28d1b5cb32f..805a1f65fa8 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -132,6 +132,9 @@ struct dsdb_control_password_change {
/* passed by dbcheck to fix duplicate linked attributes (bug #13095) */
#define DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS "1.3.6.1.4.1.7165.4.3.19.2"
+/* passed by dbcheck to fix the DN strong of a one-way-link (bug #13495) */
+#define DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME "1.3.6.1.4.1.7165.4.3.19.3"
+
/* passed when importing plain text password on upgrades */
#define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20"
diff --git a/source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif b/source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif
new file mode 100644
index 00000000000..b2142df7424
--- /dev/null
+++ b/source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif
@@ -0,0 +1,19 @@
+# record 1
+dn: OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp
+
+# record 2
+dn: OU=dangling-from,DC=release-4-5-0-pre1,DC=samba,DC=corp
+seeAlso: OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp
+
+# Referral
+ref: ldap:///CN=Configuration,DC=release-4-5-0-pre1,DC=samba,DC=corp
+
+# Referral
+ref: ldap:///DC=DomainDnsZones,DC=release-4-5-0-pre1,DC=samba,DC=corp
+
+# Referral
+ref: ldap:///DC=ForestDnsZones,DC=release-4-5-0-pre1,DC=samba,DC=corp
+
+# returned 5 records
+# 2 entries
+# 3 referrals
diff --git a/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt b/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt
new file mode 100644
index 00000000000..69d1e516d14
--- /dev/null
+++ b/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt
@@ -0,0 +1,5 @@
+Checking 228 objects
+NOTE: old (due to rename or delete) DN string component for seeAlso in object OU=dangling-from,DC=release-4-5-0-pre1,DC=samba,DC=corp - OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp
+Change DN to <GUID=20600e7c-92bb-492e-9552-f3ed7f8a2cad>;OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp? [YES]
+Fixed old DN string on attribute seeAlso
+Checked 228 objects (0 errors)
diff --git a/testprogs/blackbox/dbcheck-links.sh b/testprogs/blackbox/dbcheck-links.sh
index 778edf002c9..13811ddb461 100755
--- a/testprogs/blackbox/dbcheck-links.sh
+++ b/testprogs/blackbox/dbcheck-links.sh
@@ -205,6 +205,67 @@ check_expected_after_dbcheck_forward_link_corruption() {
fi
}
+oneway_link_corruption() {
+ #
+ # Step1: add OU "dangling-ou"
+ #
+ ldif=$PREFIX_ABS/${RELEASE}/oneway_link_corruption.ldif
+ cat > $ldif <<EOF
+dn: OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp
+changetype: add
+objectclass: organizationalUnit
+objectGUID: 20600e7c-92bb-492e-9552-f3ed7f8a2cad
+EOF
+
+ out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --relax $ldif)
+ if [ "$?" != "0" ]; then
+ echo "ldbmodify returned:\n$out"
+ return 1
+ fi
+
+ #
+ # Step2: add msExchConfigurationContainer "dangling-msexch"
+ #
+ ldif=$PREFIX_ABS/${RELEASE}/oneway_link_corruption2.ldif
+ cat > $ldif <<EOF
+dn: OU=dangling-from,DC=release-4-5-0-pre1,DC=samba,DC=corp
+changetype: add
+objectclass: organizationalUnit
+seeAlso: OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp
+EOF
+
+ out=$(TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif)
+ if [ "$?" != "0" ]; then
+ echo "ldbmodify returned:\n$out"
+ return 1
+ fi
+
+ #
+ # Step3: rename dangling-ou to dangling-ou2
+ #
+ # Because this is a one-way link we don't fix it at runtime
+ #
+ out=$(TZ=UTC $ldbrename -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb OU=dangling-ou,DC=release-4-5-0-pre1,DC=samba,DC=corp OU=dangling-ou2,DC=release-4-5-0-pre1,DC=samba,DC=corp)
+ if [ "$?" != "0" ]; then
+ echo "ldbmodify returned:\n$out"
+ return 1
+ fi
+}
+
+dbcheck_oneway_link_corruption() {
+ dbcheck "-oneway-link-corruption" "0" ""
+ return $?
+}
+
+check_expected_after_dbcheck_oneway_link_corruption() {
+ tmpldif=$PREFIX_ABS/$RELEASE/expected-after-dbcheck-oneway-link-corruption.ldif.tmp
+ TZ=UTC $ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb '(|(ou=dangling-ou)(ou=dangling-ou2)(ou=dangling-from))' -s sub -b DC=release-4-5-0-pre1,DC=samba,DC=corp --show-deleted --sorted seeAlso > $tmpldif
+ diff $tmpldif $release_dir/expected-after-dbcheck-oneway-link-corruption.ldif
+ if [ "$?" != "0" ]; then
+ return 1
+ fi
+}
+
dbcheck_dangling_multi_valued() {
$PYTHON $BINDIR/samba-tool dbcheck -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --fix --yes
@@ -276,6 +337,10 @@ if [ -d $release_dir ]; then
testit "dbcheck_forward_link_corruption" dbcheck_forward_link_corruption
testit "check_expected_after_dbcheck_forward_link_corruption" check_expected_after_dbcheck_forward_link_corruption
testit "forward_link_corruption_clean" dbcheck_clean
+ testit "oneway_link_corruption" oneway_link_corruption
+ testit "dbcheck_oneway_link_corruption" dbcheck_oneway_link_corruption
+ testit "check_expected_after_dbcheck_oneway_link_corruption" check_expected_after_dbcheck_oneway_link_corruption
+ testit "oneway_link_corruption_clean" dbcheck_clean
testit "dangling_one_way_link" dangling_one_way_link
testit "dbcheck_one_way" dbcheck_one_way
testit "dbcheck_clean2" dbcheck_clean