[SCM] Samba Shared Repository - branch master updated
Andrew Bartlett
abartlet at samba.org
Mon Jun 6 18:33:03 UTC 2016
The branch, master has been updated
via ae3d0fe selftest: Add tests to show that we can not create duplicate schema entries
via 8f93bfc samldb: Make checks for schema attributes much more strict
via cccd20f Remove the try/catch from urgent_replication.py
via f7eb865 selftest: Assert that name, the RDN attribute and actual RDN are in sync
via 39ac5ad selftest: Add another test case to replica_sync test
via 4271692 repl: Do not report all replication failures at level 0
via ca37c71 selftest/drs: Show we return the correct 3 objects for DRSUAPI_EXOP_FSMO_RID_ALLOC
via c5ed894 selftest: initial version of new repl_move test
via 9aa2d44 dsdb: Give the objectGUID ahead of LDIF dump of replicated changes
via 90581b2 dsdb: Simplify replmd_op_possible_conflict_callback behaviour
via 8938f38 dsdb: Split rename case out of replmd_op_possible_conflict_callback
via e1dcd45 repl_meta_data: Give more information on replication rename behaviour
via 7773116 repl_meta_data: Fail to replicate over local objects not NC_HEAD with a all-zero parentGUID
via fb9f526 dsdb: Give more errors in operational module when building the parentGUID
via 1e21a5a dsdb: Clearly fail to replicate objects not NC_HEAD with a all-zero parentGUID
via 449271d repl: Enforce that we have parent objects for all replicated objects
via 2d67128 dsdb: Move operational below repl_meta_data so we can query parentGUID
from a936234 Add yet another error code when forking an smbd and ctdb is not there. We can see NT_STATUS_CONNECTION_REFUSED in the logs upon such a rare case.
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit ae3d0fecd6ad7f10e80b66070dc32d1ac7099a6f
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Apr 19 13:37:19 2016 +1200
selftest: Add tests to show that we can not create duplicate schema entries
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
Autobuild-Date(master): Mon Jun 6 20:32:54 CEST 2016 on sn-devel-144
commit 8f93bfc75c6e933bd68190d5cd72678313aa1142
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Apr 19 17:22:35 2016 +1200
samldb: Make checks for schema attributes much more strict
This avoids corrupting Samba when invalid schema is imported
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
commit cccd20ff55d2aaed4fe5cf9b8727186180baf09f
Author: Andrew Bartlett <abartlet at samba.org>
Date: Mon Apr 18 14:59:21 2016 +1200
Remove the try/catch from urgent_replication.py
This meant that for ages, the duplicate OID was unnoticed, and when the syntax
was corrected recently, this caused the test to run, and so cause trouble
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz
commit f7eb865cd9e572ace6b32f1b796b0b5f113e6d5d
Author: Andrew Bartlett <abartlet at samba.org>
Date: Sun Mar 27 14:43:32 2016 +1300
selftest: Assert that name, the RDN attribute and actual RDN are in sync
This allows us to catch such errors here, rather than just on dbcheck later
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz
commit 39ac5ad90f4b174cb5ae3e92f3bdf17bc5d2cb66
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Mar 24 14:06:12 2016 +1300
selftest: Add another test case to replica_sync test
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz
commit 4271692d865029ba39ebcef334cde4342bb3f72e
Author: Andrew Bartlett <abartlet at samba.org>
Date: Mon Mar 21 15:51:12 2016 +1300
repl: Do not report all replication failures at level 0
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit ca37c7146c35cb4e672dd2b859b31bf9b10cf332
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Mar 4 13:12:42 2016 +1300
selftest/drs: Show we return the correct 3 objects for DRSUAPI_EXOP_FSMO_RID_ALLOC
This does not depend on DRSUAPI_DRS_GET_ANC.
This test is not new, but it was not previously being run.
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit c5ed8940060069c58c20e2331727f5cb7afe6fb8
Author: Andrew Bartlett <abartlet at samba.org>
Date: Wed Dec 9 14:00:10 2015 +1300
selftest: initial version of new repl_move test
This tests complex rename and modify combinations in a way that
demonstrated a number of replication failures, due to incorrect
handling in Samba when the parent of the record changes.
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz
commit 9aa2d44462a1d61a0809ccd6eb5a3d30dfaa7a55
Author: Andrew Bartlett <abartlet at samba.org>
Date: Mon Mar 21 14:06:21 2016 +1300
dsdb: Give the objectGUID ahead of LDIF dump of replicated changes
This can help isolate which object this is when the object is involved
in a rename.
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit 90581b261340f5b5c46a8e2641832ab21f83b094
Author: Andrew Bartlett <abartlet at samba.org>
Date: Sun Mar 27 15:39:03 2016 +1300
dsdb: Simplify replmd_op_possible_conflict_callback behaviour
The previous behaviour of this code was to overwrite the req->callback of the original, failed request.
This is a problem for many reasons - including that ldb_module_done() may already have been
called on that pointer.
The correct pattern is to create a new request, and to call ldb_module_done() on the parent
request (the one in ar->req) not in this one, in the error case.
We use the passed in new callback either as the callback to call on success, or
as the callback to the ADD request. We overwrite it with replmd_op_name_modify_callback
in the rename remote case, as before, but no longer modify req->callback as
this will not be used again.
This is less tricky and a little simpler to follow, as we also remove the
now unused handling for RENAME, which is in a separate routine now
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit 8938f384b7aaeea5131eb854307787805b648f34
Author: Andrew Bartlett <abartlet at samba.org>
Date: Mon Mar 21 13:32:55 2016 +1300
dsdb: Split rename case out of replmd_op_possible_conflict_callback
This avoids running this code path, originally written for the add case, in
a semi-async manner in the rename case, which caused both bugs and complexity.
This does create a deal of duplicated code, but it is easier to follow because
there are no longer special cases for ADD and RENAME in the "common" code and
the behaviour of ldb_module_done() and the callbacks is well defined and expected
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz
commit e1dcd45d9e76ff2324750133d687ba8e952a1e47
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Mar 15 15:19:21 2016 +1300
repl_meta_data: Give more information on replication rename behaviour
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit 7773116f9074d2ee89aa1828bf6a3807680d9370
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Mar 15 15:15:07 2016 +1300
repl_meta_data: Fail to replicate over local objects not NC_HEAD with a all-zero parentGUID
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit fb9f5264ef709e110bf11cff3fa0f7c371ea67ce
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Mar 15 15:11:54 2016 +1300
dsdb: Give more errors in operational module when building the parentGUID
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit 1e21a5ad619c8c3611abb0d3c3a513c62ebc7c2a
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Mar 15 15:09:50 2016 +1300
dsdb: Clearly fail to replicate objects not NC_HEAD with a all-zero parentGUID
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit 449271defc25d66bf84afa7f9b3c9591bbc762bf
Author: Andrew Bartlett <abartlet at samba.org>
Date: Wed Dec 9 17:05:56 2015 +1300
repl: Enforce that we have parent objects for all replicated objects
The creating of replicated objects without their parent object allows database corruption as they can end up under
the wrong object. We need to re-try the replication with the DRSUAPI_DRS_GET_ANC flag
set to get the objects in tree order.
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit 2d67128814f27731d1cd7d137e822c894ab87a4b
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Mar 15 15:11:30 2016 +1300
dsdb: Move operational below repl_meta_data so we can query parentGUID
This avoids re-adding the same code in repl_meta_data or making a shared subroutine
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz
-----------------------------------------------------------------------
Summary of changes:
source4/dsdb/repl/drepl_out_helpers.c | 26 +-
source4/dsdb/repl/replicated_objects.c | 37 +-
source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 3 +-
source4/dsdb/samdb/ldb_modules/operational.c | 4 +-
source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 558 +++++++++----
source4/dsdb/samdb/ldb_modules/samba_dsdb.c | 2 +-
source4/dsdb/samdb/ldb_modules/samldb.c | 269 +++---
source4/dsdb/samdb/samdb.h | 7 +-
source4/dsdb/tests/python/deletetest.py | 4 +-
source4/dsdb/tests/python/ldap_schema.py | 657 ++++++++++++++-
source4/dsdb/tests/python/urgent_replication.py | 14 +-
source4/selftest/tests.py | 10 +
source4/torture/drs/python/delete_object.py | 12 +-
source4/torture/drs/python/getnc_exop.py | 109 ++-
source4/torture/drs/python/repl_move.py | 929 +++++++++++++++++++++
source4/torture/drs/python/replica_sync.py | 127 +++
16 files changed, 2481 insertions(+), 287 deletions(-)
create mode 100644 source4/torture/drs/python/repl_move.py
Changeset truncated at 500 lines:
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index 54f44c6..6493c1e 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -458,6 +458,10 @@ static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req)
replica_flags = rf1->replica_flags;
highwatermark = rf1->highwatermark;
+ if (state->op->options & DRSUAPI_DRS_GET_ANC) {
+ replica_flags |= DRSUAPI_DRS_GET_ANC;
+ }
+
if (partition->partial_replica) {
status = dreplsrv_get_gc_partial_attribute_set(service, r, &pas);
if (!NT_STATUS_IS_OK(status)) {
@@ -873,7 +877,27 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
talloc_free(objects);
if (!W_ERROR_IS_OK(status)) {
- nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+
+ /*
+ * If we failed to apply the records due to a missing
+ * parent, try again after asking for the parent
+ * records first. Because we don't update the
+ * highwatermark, we start this part of the cycle
+ * again.
+ */
+ if (((state->op->options & DRSUAPI_DRS_GET_ANC) == 0)
+ && W_ERROR_EQUAL(status, WERR_DS_DRA_MISSING_PARENT)) {
+ state->op->options |= DRSUAPI_DRS_GET_ANC;
+ DEBUG(4,("Missing parent object when we didn't set the DRSUAPI_DRS_GET_ANC flag, retrying\n"));
+ dreplsrv_op_pull_source_get_changes_trigger(req);
+ return;
+ } else if (((state->op->options & DRSUAPI_DRS_GET_ANC))
+ && W_ERROR_EQUAL(status, WERR_DS_DRA_MISSING_PARENT)) {
+ DEBUG(1,("Missing parent object despite setting DRSUAPI_DRS_GET_ANC flag\n"));
+ nt_status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+ } else {
+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+ }
DEBUG(0,("Failed to commit objects: %s/%s\n",
win_errstr(status), nt_errstr(nt_status)));
tevent_req_nterror(req, nt_status);
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 44a766b..674074c 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -348,15 +348,12 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
TALLOC_CTX *mem_ctx,
struct dsdb_extended_replicated_object *out)
{
- NTSTATUS nt_status;
WERROR status = WERR_OK;
uint32_t i;
struct ldb_message *msg;
struct replPropertyMetaDataBlob *md;
int instanceType;
struct ldb_message_element *instanceType_e = NULL;
- struct ldb_val guid_value;
- struct ldb_val parent_guid_value;
NTTIME whenChanged = 0;
time_t whenChanged_t;
const char *whenChanged_s;
@@ -615,23 +612,22 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
whenChanged_s = ldb_timestring(msg, whenChanged_t);
W_ERROR_HAVE_NO_MEMORY(whenChanged_s);
- nt_status = GUID_to_ndr_blob(&in->object.identifier->guid, msg, &guid_value);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ntstatus_to_werror(nt_status);
- }
+ out->object_guid = in->object.identifier->guid;
- if (in->parent_object_guid) {
- nt_status = GUID_to_ndr_blob(in->parent_object_guid, msg, &parent_guid_value);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ntstatus_to_werror(nt_status);
+ if (in->parent_object_guid == NULL) {
+ out->parent_guid = NULL;
+ if ((instanceType & INSTANCE_TYPE_IS_NC_HEAD) == 0) {
+ DEBUG(0, ("Refusing to replicate %s from a server that did not provide a parentGUID!\n",
+ ldb_dn_get_linearized(msg->dn)));
+ return WERR_DS_DRA_INCONSISTENT_DIT;
}
} else {
- parent_guid_value = data_blob_null;
+ out->parent_guid = talloc(mem_ctx, struct GUID);
+ W_ERROR_HAVE_NO_MEMORY(out->parent_guid);
+ *out->parent_guid = *in->parent_object_guid;
}
out->msg = msg;
- out->guid_value = guid_value;
- out->parent_guid_value = parent_guid_value;
out->when_changed = whenChanged_s;
out->meta_data = md;
return WERR_OK;
@@ -840,10 +836,19 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
dsdb_reference_schema(ldb, cur_schema, false);
}
- DEBUG(0,("Failed to apply records: %s: %s\n",
- ldb_errstring(ldb), ldb_strerror(ret)));
+ if (!W_ERROR_EQUAL(objects->error, WERR_DS_DRA_MISSING_PARENT)) {
+ DEBUG(1,("Failed to apply records: %s: %s\n",
+ ldb_errstring(ldb), ldb_strerror(ret)));
+ } else {
+ DEBUG(3,("Missing parent while attempting to apply records: %s\n",
+ ldb_errstring(ldb)));
+ }
ldb_transaction_cancel(ldb);
TALLOC_FREE(tmp_ctx);
+
+ if (!W_ERROR_IS_OK(objects->error)) {
+ return objects->error;
+ }
return WERR_FOOBAR;
}
talloc_free(ext_res);
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
index 316dcf8..e051913 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
@@ -512,6 +512,7 @@ static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares)
struct ldb_request *search_req;
struct ldb_dn *base_dn;
int ret;
+ static const char *attrs[] = {"nTSecurityDescriptor", "*", NULL};
ac = talloc_get_type(req->context, struct oc_context);
ldb = ldb_module_get_ctx(ac->module);
@@ -544,7 +545,7 @@ static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares)
: ac->req->op.mod.message->dn;
ret = ldb_build_search_req(&search_req, ldb, ac, base_dn,
LDB_SCOPE_BASE, "(objectClass=*)",
- NULL, NULL, ac,
+ attrs, NULL, ac,
get_search_callback, ac->req);
LDB_REQ_SET_LOCATION(search_req);
if (ret != LDB_SUCCESS) {
diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c
index 0dd420a..4205c4b 100644
--- a/source4/dsdb/samdb/ldb_modules/operational.c
+++ b/source4/dsdb/samdb/ldb_modules/operational.c
@@ -352,7 +352,7 @@ static int construct_parent_guid(struct ldb_module *module,
if (parent_dn == NULL) {
DEBUG(4,(__location__ ": Failed to find parent for dn %s\n",
ldb_dn_get_linearized(msg->dn)));
- return LDB_SUCCESS;
+ return LDB_ERR_OTHER;
}
ret = dsdb_module_search_dn(module, msg, &parent_res, parent_dn, attrs2,
DSDB_FLAG_NEXT_MODULE |
@@ -372,7 +372,7 @@ static int construct_parent_guid(struct ldb_module *module,
parent_guid = ldb_msg_find_ldb_val(parent_res->msgs[0], "objectGUID");
if (!parent_guid) {
talloc_free(parent_res);
- return LDB_SUCCESS;
+ return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
}
v = data_blob_dup_talloc(parent_res, *parent_guid);
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 6596d45..f1d3958 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -91,6 +91,7 @@ struct replmd_replicated_request {
struct dsdb_extended_replicated_objects *objs;
struct ldb_message *search_msg;
+ struct GUID local_parent_guid;
uint64_t seq_num;
bool is_urgent;
@@ -3527,6 +3528,10 @@ static int replmd_replicated_request_werror(struct replmd_replicated_request *ar
{
int ret = LDB_ERR_OTHER;
/* TODO: do some error mapping */
+
+ /* Let the caller know the full WERROR */
+ ar->objs->error = status;
+
return ret;
}
@@ -3755,7 +3760,7 @@ static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_re
}
/*
- callback for replmd_replicated_apply_add() and replmd_replicated_handle_rename()
+ callback for replmd_replicated_apply_add()
This copes with the creation of conflict records in the case where
the DN exists, but with a different objectGUID
*/
@@ -3773,36 +3778,37 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
bool rename_incoming_record, rodc;
struct replPropertyMetaData1 *rmd_name, *omd_name;
struct ldb_message *msg;
+ struct ldb_request *down_req = NULL;
- req->callback = callback;
-
- if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
- /* call the normal callback for everything except
- conflicts */
- return ldb_module_done(req, ares->controls, ares->response, ares->error);
+ /* call the normal callback for success */
+ if (ares->error == LDB_SUCCESS) {
+ return callback(req, ares);
}
- ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
- if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to determine if we are an RODC when attempting to form conflict DN: %s", ldb_errstring(ldb_module_get_ctx(ar->module)));
- return ldb_module_done(req, ares->controls, ares->response, LDB_ERR_OPERATIONS_ERROR);
- }
/*
* we have a conflict, and need to decide if we will keep the
* new record or the old record
*/
msg = ar->objs->objects[ar->index_current].msg;
+ conflict_dn = msg->dn;
+
+ /* For failures other than conflicts, fail the whole operation here */
+ if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote add of %s: %s",
+ ldb_dn_get_linearized(conflict_dn),
+ ldb_errstring(ldb_module_get_ctx(ar->module)));
+
+ return ldb_module_done(ar->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to determine if we are an RODC when attempting to form conflict DN: %s", ldb_errstring(ldb_module_get_ctx(ar->module)));
+ return ldb_module_done(ar->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
- switch (req->operation) {
- case LDB_ADD:
- conflict_dn = msg->dn;
- break;
- case LDB_RENAME:
- conflict_dn = req->op.rename.newdn;
- break;
- default:
- return ldb_module_done(req, ares->controls, ares->response, ldb_module_operr(ar->module));
}
if (rodc) {
@@ -3821,7 +3827,7 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
/*
* first we need the replPropertyMetaData attribute from the
- * old record
+ * local, conflicting record
*/
ret = dsdb_module_search_dn(ar->module, req, &res, conflict_dn,
attrs,
@@ -3868,23 +3874,6 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
struct GUID guid;
struct ldb_dn *new_dn;
- /*
- * We want to run the original callback here, which
- * will return LDB_ERR_ENTRY_ALREADY_EXISTS to the
- * caller, which will in turn know to rename the
- * incoming record. The error string is set in case
- * this isn't handled properly at some point in the
- * future.
- */
- if (req->operation == LDB_RENAME) {
- ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
- "Unable to handle incoming renames where this would "
- "create a conflict. Incoming record is %s (caller to handle)\n",
- ldb_dn_get_extended_linearized(req, conflict_dn, 1));
-
- goto failed;
- }
-
guid = samdb_result_guid(msg, "objectGUID");
if (GUID_all_zero(&guid)) {
DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n",
@@ -3901,12 +3890,9 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
DEBUG(2,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n",
ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
- /* re-submit the request, but with a different
- callback, so we don't loop forever. */
+ /* re-submit the request, but with the new DN */
+ callback = replmd_op_name_modify_callback;
msg->dn = new_dn;
- req->callback = replmd_op_name_modify_callback;
-
- return ldb_next_request(ar->module, req);
} else {
/* we are renaming the existing record */
struct GUID guid;
@@ -3948,15 +3934,55 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
goto failed;
}
- return ldb_next_request(ar->module, req);
+ DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated creation of '%s'\n",
+ ldb_dn_get_linearized(req->op.add.message->dn)));
+ }
+
+ ret = ldb_build_add_req(&down_req,
+ ldb_module_get_ctx(ar->module),
+ req,
+ msg,
+ ar->controls,
+ ar,
+ callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ goto failed;
+ }
+ LDB_REQ_SET_LOCATION(down_req);
+
+ /* current partition control needed by "repmd_op_callback" */
+ ret = ldb_request_add_control(down_req,
+ DSDB_CONTROL_CURRENT_PARTITION_OID,
+ false, NULL);
+ if (ret != LDB_SUCCESS) {
+ return replmd_replicated_request_error(ar, ret);
}
+ if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
+ /* this tells the partition module to make it a
+ partial replica if creating an NC */
+ ret = ldb_request_add_control(down_req,
+ DSDB_CONTROL_PARTIAL_REPLICA,
+ false, NULL);
+ if (ret != LDB_SUCCESS) {
+ return replmd_replicated_request_error(ar, ret);
+ }
+ }
+
+ /*
+ * Finally we re-run the add, otherwise the new record won't
+ * exist, as we are here because of that exact failure!
+ */
+ return ldb_next_request(ar->module, down_req);
failed:
- /* on failure do the original callback. This means replication
- * will stop with an error, but there is not much else we can
- * do
+
+ /* on failure make the caller get the error. This means
+ * replication will stop with an error, but there is not much
+ * else we can do.
*/
- return ldb_module_done(req, ares->controls, ares->response, ares->error);
+ return ldb_module_done(ar->req, NULL, NULL,
+ ret);
}
/*
@@ -3979,16 +4005,6 @@ static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *are
}
/*
- callback for replmd_replicated_handle_rename()
- This copes with the creation of conflict records in the case where
- the DN exists, but with a different objectGUID
- */
-static int replmd_op_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
-{
- return replmd_op_possible_conflict_callback(req, ares, ldb_modify_default_callback);
-}
-
-/*
this is called when a new object comes in over DRS
*/
static int replmd_replicated_apply_add(struct replmd_replicated_request *ar)
@@ -4014,7 +4030,9 @@ static int replmd_replicated_apply_add(struct replmd_replicated_request *ar)
return replmd_replicated_request_error(ar, ret);
}
- ret = ldb_msg_add_value(msg, "objectGUID", &ar->objs->objects[ar->index_current].guid_value, NULL);
+ ret = dsdb_msg_add_guid(msg,
+ &ar->objs->objects[ar->index_current].object_guid,
+ "objectGUID");
if (ret != LDB_SUCCESS) {
return replmd_replicated_request_error(ar, ret);
}
@@ -4056,8 +4074,12 @@ static int replmd_replicated_apply_add(struct replmd_replicated_request *ar)
}
if (DEBUGLVL(4)) {
+ struct GUID_txt_buf guid_txt;
+
char *s = ldb_ldif_message_string(ldb, ar, LDB_CHANGETYPE_ADD, msg);
- DEBUG(4, ("DRS replication add message:\n%s\n", s));
+ DEBUG(4, ("DRS replication add message of %s:\n%s\n",
+ GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid, &guid_txt),
+ s));
talloc_free(s);
}
@@ -4154,12 +4176,14 @@ static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request
return ldb_module_done(ar->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
}
- if (ares->error != LDB_SUCCESS &&
- ares->error != LDB_ERR_NO_SUCH_OBJECT) {
- /*
- * TODO: deal with the above error that the parent object doesn't exist
- */
+ /*
+ * The error NO_SUCH_OBJECT is not expected, unless the search
+ * base is the partition DN, and that case doesn't happen here
+ * because then we wouldn't get a parent_guid_value in any
+ * case.
+ */
+ if (ares->error != LDB_SUCCESS) {
return ldb_module_done(ar->req, ares->controls,
ares->response, ares->error);
}
@@ -4217,9 +4241,13 @@ static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request
}
ar->objs->objects[ar->index_current].last_known_parent
= talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn);
+
} else {
- parent_dn = parent_msg->dn;
+ parent_dn
+ = talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn);
+
}
+ ar->objs->objects[ar->index_current].local_parent_dn = parent_dn;
comp_num = ldb_dn_get_comp_num(msg->dn);
if (comp_num > 1) {
@@ -4239,6 +4267,32 @@ static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request
break;
case LDB_REPLY_DONE:
+
+ if (ar->objs->objects[ar->index_current].local_parent_dn == NULL) {
+ struct GUID_txt_buf str_buf;
+ if (ar->search_msg != NULL) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
+ "No parent with GUID %s found for object locally known as %s",
+ GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid, &str_buf),
+ ldb_dn_get_linearized(ar->search_msg->dn));
+ } else {
+ ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
+ "No parent with GUID %s found for object remotely known as %s",
+ GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid, &str_buf),
+ ldb_dn_get_linearized(ar->objs->objects[ar->index_current].msg->dn));
+ }
+
+ /*
+ * This error code is really important, as it
+ * is the flag back to the callers to retry
+ * this with DRSUAPI_DRS_GET_ANC, and so get
+ * the parent objects before the child
+ * objects
+ */
+ return ldb_module_done(ar->req, NULL, NULL,
+ replmd_replicated_request_werror(ar, WERR_DS_DRA_MISSING_PARENT));
+ }
+
if (ar->search_msg != NULL) {
ret = replmd_replicated_apply_merge(ar);
} else {
@@ -4268,10 +4322,11 @@ static int replmd_replicated_apply_search_for_parent(struct replmd_replicated_re
char *filter;
struct ldb_request *search_req;
static const char *attrs[] = {"isDeleted", NULL};
+ struct GUID_txt_buf guid_str_buf;
ldb = ldb_module_get_ctx(ar->module);
- if (!ar->objs->objects[ar->index_current].parent_guid_value.data) {
+ if (ar->objs->objects[ar->index_current].parent_guid == NULL) {
if (ar->search_msg != NULL) {
return replmd_replicated_apply_merge(ar);
} else {
@@ -4279,12 +4334,11 @@ static int replmd_replicated_apply_search_for_parent(struct replmd_replicated_re
}
}
- tmp_str = ldb_binary_encode(ar, ar->objs->objects[ar->index_current].parent_guid_value);
- if (!tmp_str) return replmd_replicated_request_werror(ar, WERR_NOMEM);
+ tmp_str = GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
+ &guid_str_buf);
filter = talloc_asprintf(ar, "(objectGUID=%s)", tmp_str);
if (!filter) return replmd_replicated_request_werror(ar, WERR_NOMEM);
- talloc_free(tmp_str);
ret = ldb_build_search_req(&search_req,
ldb,
--
Samba Shared Repository
More information about the samba-cvs
mailing list