[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Tue Jul 31 08:10:02 MDT 2012


The branch, master has been updated
       via  23df816 VERSION: Move on to beta6!
       via  50d6483 VERSION: Mark as the beta5 release
       via  fb24f47 WHATSNEW: prepare for 4.0 beta5
       via  3178741 s4-repl: Add tests for add replication conflicts and use of LostAndFound
       via  6d1b8ff s4-dsdb: Replace any existing lastKnownParent attribute during delete
       via  fcb54ca s4-dsdb: Improve tracing in repl_meta_data
       via  bc5be09 s4-dsdb: Handle rename conflicts in both directions
       via  8208d7b lib/ldb: Ensure rename target does not exist before deleting old record
       via  221cd52 s4-dsdb: Request extended DN and show deleted when searching for a possible parent
      from  eaa381a s3: Fix Coverity ID 710791 Resource leak

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 23df816328bf10f06a7c7a018c7a1e896c62f3bf
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jul 31 12:25:56 2012 +1000

    VERSION: Move on to beta6!
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Tue Jul 31 16:09:23 CEST 2012 on sn-devel-104

commit 50d6483ab8acd9a2af7558b6831c170a5bce3721
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jul 31 12:25:16 2012 +1000

    VERSION: Mark as the beta5 release

commit fb24f471be6af42a5a1f49c58d4d3e52e25f10b6
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jul 31 12:24:49 2012 +1000

    WHATSNEW: prepare for 4.0 beta5

commit 31787417ca9d01965a9f5221ff6adc48a4b1a15f
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Jul 30 16:00:58 2012 +1000

    s4-repl: Add tests for add replication conflicts and use of LostAndFound
    
    LostAndFound is used when we find children of a deleted object that are not themselves deleted.
    
    Andrew Bartlett

commit 6d1b8ff8a7b803601f8142396e659d0f1dbef331
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jul 31 10:47:57 2012 +1000

    s4-dsdb: Replace any existing lastKnownParent attribute during delete
    
    This allows a lastKnownParent from LostAndFound to be replaced.
    
    Andrew Bartlett

commit fcb54ca25f0a28940d239c457ef1a295d6e5e325
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jul 31 10:18:43 2012 +1000

    s4-dsdb: Improve tracing in repl_meta_data
    
    When we call ldb_module_done() rather than just calling the callback, we make log entries
    that are critical in debugging.
    
    Andrew Bartlett

commit bc5be09bae77c5e34380a2204be2f489f45ed85b
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Jul 30 12:11:35 2012 +1000

    s4-dsdb: Handle rename conflicts in both directions
    
    Previously we would only consider renaming the local object, now we can cope with
    renaming the remote object as well.
    
    This should avoid most of the cases where Samba AD replication can just stop.
    
    Andrew Bartlett

commit 8208d7b2c207c39c3d45f96f85728c233dce126d
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jul 31 10:17:20 2012 +1000

    lib/ldb: Ensure rename target does not exist before deleting old record
    
    This is all in a transaction, but when we are handling rename errors in the repl_meta_data
    module, we key off the error, and do not close the transaction.  We found that the
    old record was gone and so could not try renaming it again to a conflict DN.
    
    Andrew Bartlett

commit 221cd524e31fce5efa2de179074cfe97bf2c909c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jul 31 17:10:42 2012 +1000

    s4-dsdb: Request extended DN and show deleted when searching for a possible parent
    
    This fixes up the lastKnownParent attribute on lostAndFound objects to have a GUID
    
    (found by dbcheck).
    
    Andrew Bartlett

-----------------------------------------------------------------------

Summary of changes:
 VERSION                                            |    2 +-
 WHATSNEW.txt                                       |   54 ++--
 lib/ldb/ABI/{ldb-1.1.6.sigs => ldb-1.1.9.sigs}     |    0
 ...pyldb-util-1.1.2.sigs => pyldb-util-1.1.9.sigs} |    0
 lib/ldb/ldb_tdb/ldb_tdb.c                          |   42 +++-
 lib/ldb/wscript                                    |    2 +-
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c    |  159 +++++++----
 source4/torture/drs/python/drs_base.py             |    8 +
 source4/torture/drs/python/replica_sync.py         |  301 ++++++++++++++++++++
 9 files changed, 481 insertions(+), 87 deletions(-)
 copy lib/ldb/ABI/{ldb-1.1.6.sigs => ldb-1.1.9.sigs} (100%)
 copy lib/ldb/ABI/{pyldb-util-1.1.2.sigs => pyldb-util-1.1.9.sigs} (100%)


Changeset truncated at 500 lines:

diff --git a/VERSION b/VERSION
index a9c261b..1012cd9 100644
--- a/VERSION
+++ b/VERSION
@@ -67,7 +67,7 @@ SAMBA_VERSION_ALPHA_RELEASE=
 # e.g. SAMBA_VERSION_BETA_RELEASE=1                    #
 #  ->  "4.0.0beta1"                                    #
 ########################################################
-SAMBA_VERSION_BETA_RELEASE=5
+SAMBA_VERSION_BETA_RELEASE=6
 
 ########################################################
 # For 'pre' releases the version will be               #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index b7af995..1b08ff3 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,4 @@
-What's new in Samba 4.0 beta4
+What's new in Samba 4.0 beta5
 =============================
 
 Samba 4.0 will be the next version of the Samba suite and incorporates
@@ -11,7 +11,7 @@ and above.
 WARNINGS
 ========
 
-Samba 4.0 beta4 is not a final Samba release, however we are now making
+Samba 4.0 beta5 is not a final Samba release, however we are now making
 good progress towards a Samba 4.0 release, of which this is a preview.
 Be aware the this release contains the best of all of Samba's
 technology parts, both a file server (that you can reasonably expect
@@ -94,55 +94,61 @@ Python programs to interface to Samba's internals, and many tools and
 internal workings of the DC code is now implemented in python.
 
 
-CHANGES SINCE beta3
+CHANGES SINCE beta4
 =====================
 
-For a list of changes since beta3, please see the git log.
+For a list of changes since beta4, please see the git log.
 
 $ git clone git://git.samba.org/samba.git
 $ cd samba.git
-$ git log samba-4.0.0beta3..samba-4.0.0beta4
+$ git log samba-4.0.0beta4..samba-4.0.0beta5
 
 Some major user-visible changes include:
 
-- The issue with beta3 being unable to build with a released version of
+- The issue with beta4 being unable to build with a released version of
   ldb has been resolved. 
 
-- A new tool 'samba-tool domain dcpromo' has been added to allow the
-  promotion of existing domain member accounts to a DC without creating
-  a new SID
+- The two parameter tables for our two smb.conf parsing engines have
+  been merged.  This removes the ugly (but harmless) "unknown
+  parameter xxx" warnings, particularly from the smbd child process.
 
-- When provisioning with --use_rfc2307=yes we will populate the
-  subtree CN=ypServ30,CN=RpcServices,CN=System,${DOMAINDN}. This makes
-  it possible to manipulate the posix attributes via ADUC.
+- Major issues have been fixed in conflict and missing/deleted parent
+  handling in or DRS replication engine.
 
-- Improved 'samba-tool gpo' subcommands
+- Safety improvements to prevent corruption of read-write replicas
+  by manual replication from a read-only replica.
 
-- --disable-ntdb now works properly
+- Improvements to dbcheck to correct incorrect instanceType values from
+  the above and to relocate objects with missing parents.
 
-- Bug 9026 - 3.6.6 upgrade from 3.5.x fails with "Couldn't migrate
-  printers tdb file: NT_STATUS_NO_MEMORY" has been resolved
+- smbd no longer places all accounts in the 'Domain Users' of the AD
+  domain to which it is joined
 
-- Bug 9016 - Connection to outbound trusted domain goes offline has
-  been resolved
+- AES support in NETLOGON Schannel
+
+- DCE/RPC timeout handling no longer crashes
+
+- "socket address" is now "nbt client socket address" as it only
+  controls the binding of the NetBIOS client, not other protocols.
+  See 'bind interfaces only = yes'.  This parameter is also now depricated.
+
+- nmbd now always binds to it's broadcast sockets explicitly, rather
+  than just relying on the socket address above.
 
 Less visible, but important changes under the hood include:
 
 - Continued work to support SMB2 and SMB3
 
-- Correct restrictions and permissions on LSA calls over TCP and via
-  Schannel have been implemented and tested
-
 - Continued work to use async IO to improve file server performance.
 
+- Patches to ensure that talloc_tos() and talloc_stackframe() are
+  always used correctly.
+
 KNOWN ISSUES
 ============
 
 - This release makes the s3fs file server the default, as this is the
   file server combination we will use for the Samba 4.0 release.
-  Users should still expect some rough edges: in particular, there are
-  warnings about invalid parameters from the two respective parameter
-  parsing engines.
 
 - Modifying of group policies by members of the Domain Administrators
   group is not possible with the s3fs file server, only with the ntvfs
diff --git a/lib/ldb/ABI/ldb-1.1.6.sigs b/lib/ldb/ABI/ldb-1.1.9.sigs
similarity index 100%
copy from lib/ldb/ABI/ldb-1.1.6.sigs
copy to lib/ldb/ABI/ldb-1.1.9.sigs
diff --git a/lib/ldb/ABI/pyldb-util-1.1.2.sigs b/lib/ldb/ABI/pyldb-util-1.1.9.sigs
similarity index 100%
copy from lib/ldb/ABI/pyldb-util-1.1.2.sigs
copy to lib/ldb/ABI/pyldb-util-1.1.9.sigs
diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c
index 14ffcf4..cc1586d 100644
--- a/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -973,9 +973,12 @@ static int ltdb_modify(struct ltdb_context *ctx)
 static int ltdb_rename(struct ltdb_context *ctx)
 {
 	struct ldb_module *module = ctx->module;
+	void *data = ldb_module_get_private(module);
+	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
 	struct ldb_request *req = ctx->req;
 	struct ldb_message *msg;
 	int ret = LDB_SUCCESS;
+	TDB_DATA tdb_key, tdb_key_old;
 
 	ldb_request_set_state(req, LDB_ASYNC_PENDING);
 
@@ -988,25 +991,58 @@ static int ltdb_rename(struct ltdb_context *ctx)
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
-	/* in case any attribute of the message was indexed, we need
-	   to fetch the old record */
+	/* we need to fetch the old record to re-add under the new name */
 	ret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
 	if (ret != LDB_SUCCESS) {
 		/* not finding the old record is an error */
 		return ret;
 	}
 
+	/* We need to, before changing the DB, check if the new DN
+	 * exists, so we can return this error to the caller with an
+	 * unmodified DB */
+	tdb_key = ltdb_key(module, req->op.rename.newdn);
+	if (!tdb_key.dptr) {
+		talloc_free(msg);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	tdb_key_old = ltdb_key(module, req->op.rename.olddn);
+	if (!tdb_key_old.dptr) {
+		talloc_free(msg);
+		talloc_free(tdb_key.dptr);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	/* Only declare a conflict if the new DN already exists, and it isn't a case change on the old DN */
+	if (tdb_key_old.dsize != tdb_key.dsize || memcmp(tdb_key.dptr, tdb_key_old.dptr, tdb_key.dsize) != 0) {
+		if (tdb_exists(ltdb->tdb, tdb_key)) {
+			talloc_free(tdb_key_old.dptr);
+			talloc_free(tdb_key.dptr);
+			ldb_asprintf_errstring(ldb_module_get_ctx(module),
+					       "Entry %s already exists",
+					       ldb_dn_get_linearized(msg->dn));
+			/* finding the new record already in the DB is an error */
+			talloc_free(msg);
+			return LDB_ERR_ENTRY_ALREADY_EXISTS;
+		}
+	}
+	talloc_free(tdb_key_old.dptr);
+	talloc_free(tdb_key.dptr);
+
 	/* Always delete first then add, to avoid conflicts with
 	 * unique indexes. We rely on the transaction to make this
 	 * atomic
 	 */
 	ret = ltdb_delete_internal(module, msg->dn);
 	if (ret != LDB_SUCCESS) {
+		talloc_free(msg);
 		return ret;
 	}
 
 	msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
 	if (msg->dn == NULL) {
+		talloc_free(msg);
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
@@ -1016,6 +1052,8 @@ static int ltdb_rename(struct ltdb_context *ctx)
 	 */
 	ret = ltdb_add_internal(module, msg, false);
 
+	talloc_free(msg);
+
 	return ret;
 }
 
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index 20c21b1..2971842 100755
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 APPNAME = 'ldb'
-VERSION = '1.1.8'
+VERSION = '1.1.9'
 
 blddir = 'bin'
 
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 930696a..4bfbee1 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -2987,7 +2987,7 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 			talloc_free(tmp_ctx);
 			return ret;
 		}
-		msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD;
+		msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
 	}
 
 	switch (next_deletion_state){
@@ -3333,6 +3333,7 @@ static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_re
 {
 	struct replmd_replicated_request *ar =
 		talloc_get_type_abort(req->context, struct replmd_replicated_request);
+	struct ldb_dn *conflict_dn;
 	int ret;
 
 	if (ares->error != LDB_SUCCESS) {
@@ -3340,8 +3341,19 @@ static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_re
 		return replmd_op_callback(req, ares);
 	}
 
+	switch (req->operation) {
+	case LDB_ADD:
+		conflict_dn = req->op.add.message->dn;
+		break;
+	case LDB_MODIFY:
+		conflict_dn = req->op.mod.message->dn;
+		break;
+	default:
+		smb_panic("replmd_op_name_modify_callback called in unknown circumstances");
+	}
+
 	/* perform a modify of the rDN and name of the record */
-	ret = replmd_name_modify(ar, req, req->op.add.message->dn);
+	ret = replmd_name_modify(ar, req, conflict_dn);
 	if (ret != LDB_SUCCESS) {
 		ares->error = ret;
 		return replmd_op_callback(req, ares);
@@ -3391,36 +3403,42 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
 	struct ldb_result *res;
 	const char *attrs[] = { "replPropertyMetaData", "objectGUID", NULL };
 	int ret;
-	const struct ldb_val *rmd_value, *omd_value;
-	struct replPropertyMetaDataBlob omd, rmd;
+	const struct ldb_val *omd_value;
+	struct replPropertyMetaDataBlob omd, *rmd;
 	enum ndr_err_code ndr_err;
 	bool rename_incoming_record, rodc;
 	struct replPropertyMetaData1 *rmd_name, *omd_name;
+	struct ldb_message *msg;
+
+	req->callback = callback;
 
 	if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
 		/* call the normal callback for everything except
 		   conflicts */
-		return callback(req, ares);
+		return ldb_module_done(req, ares->controls, ares->response, ares->error);
 	}
 
 	ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
 	if (ret != LDB_SUCCESS) {
-		return ret;
+		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;
+
 	switch (req->operation) {
 	case LDB_ADD:
-		conflict_dn = req->op.add.message->dn;
+		conflict_dn = msg->dn;
 		break;
 	case LDB_RENAME:
 		conflict_dn = req->op.rename.newdn;
 		break;
 	default:
-		return ldb_module_operr(ar->module);
+		return ldb_module_done(req, ares->controls, ares->response, ldb_module_operr(ar->module));
 	}
 
 	if (rodc) {
@@ -3467,28 +3485,11 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
 		goto failed;
 	}
 
-	/*
-	 * and the replPropertyMetaData attribute from the
-	 * new record
-	 */
-	rmd_value = ldb_msg_find_ldb_val(req->op.add.message, "replPropertyMetaData");
-	if (rmd_value == NULL) {
-		DEBUG(0,(__location__ ": Unable to find replPropertyMetaData for new record '%s'\n",
-			 ldb_dn_get_linearized(conflict_dn)));
-		goto failed;
-	}
-
-	ndr_err = ndr_pull_struct_blob(rmd_value, req, &rmd,
-				       (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
-	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-		DEBUG(0,(__location__ ": Failed to parse new replPropertyMetaData for %s\n",
-			 ldb_dn_get_linearized(conflict_dn)));
-		goto failed;
-	}
+	rmd = ar->objs->objects[ar->index_current].meta_data;
 
 	/* we decide which is newer based on the RPMD on the name
 	   attribute.  See [MS-DRSR] ResolveNameConflict */
-	rmd_name = replmd_replPropertyMetaData1_find_attid(&rmd, DRSUAPI_ATTID_name);
+	rmd_name = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name);
 	omd_name = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name);
 	if (!rmd_name || !omd_name) {
 		DEBUG(0,(__location__ ": Failed to find name attribute in replPropertyMetaData for %s\n",
@@ -3504,14 +3505,24 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
 		struct ldb_dn *new_dn;
 		struct ldb_message *new_msg;
 
+		/*
+		 * 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) {
-			DEBUG(0,(__location__ ": Unable to handle incoming renames where this would "
-				 "create a conflict. Incoming record is %s\n",
-				 ldb_dn_get_extended_linearized(req, conflict_dn, 1)));
+			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(req->op.add.message, "objectGUID");
+		guid = samdb_result_guid(msg, "objectGUID");
 		if (GUID_all_zero(&guid)) {
 			DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n",
 				 ldb_dn_get_linearized(conflict_dn)));
@@ -3527,27 +3538,17 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
 		DEBUG(1,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n",
 			 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
 
-		switch (req->operation) {
-		case LDB_ADD:
-			/* re-submit the request, but with a different
-			   callback, so we don't loop forever. */
-			new_msg = ldb_msg_copy_shallow(req, req->op.add.message);
-			if (!new_msg) {
-				goto failed;
-				DEBUG(0,(__location__ ": Failed to copy conflict DN message for %s\n",
-					 ldb_dn_get_linearized(conflict_dn)));
-			}
-			new_msg->dn = new_dn;
-			req->op.add.message = new_msg;
-			req->callback = replmd_op_name_modify_callback;
-			break;
-		case LDB_RENAME:
-			req->op.rename.newdn = new_dn;
-			req->callback = callback;
-			break;
-		default:
-			return ldb_module_operr(ar->module);
+		/* re-submit the request, but with a different
+		   callback, so we don't loop forever. */
+		new_msg = ldb_msg_copy_shallow(req, msg);
+		if (!new_msg) {
+			goto failed;
+			DEBUG(0,(__location__ ": Failed to copy conflict DN message for %s\n",
+				 ldb_dn_get_linearized(conflict_dn)));
 		}
+		new_msg->dn = new_dn;
+		req->op.add.message = new_msg;
+		req->callback = replmd_op_name_modify_callback;
 
 		return ldb_next_request(ar->module, req);
 	} else {
@@ -3591,8 +3592,6 @@ static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct
 			goto failed;
 		}
 
-		req->callback = callback;
-
 		return ldb_next_request(ar->module, req);
 	}
 
@@ -3601,7 +3600,7 @@ failed:
 	 * will stop with an error, but there is not much else we can
 	 * do
 	 */
-	return callback(req, ares);
+	return ldb_module_done(req, ares->controls, ares->response, ares->error);
 }
 
 /*
@@ -3894,8 +3893,10 @@ static int replmd_replicated_apply_search_for_parent(struct replmd_replicated_re
 				   ar->req);
 	LDB_REQ_SET_LOCATION(search_req);
 
-	ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
-				      true, NULL);
+	ret = dsdb_request_add_controls(search_req, 
+					DSDB_SEARCH_SHOW_RECYCLED|
+					DSDB_SEARCH_SHOW_DELETED|
+					DSDB_SEARCH_SHOW_EXTENDED_DN);
 	if (ret != LDB_SUCCESS) {
 		return ret;
 	}
@@ -4001,9 +4002,11 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar)
 	uint32_t j,ni=0;
 	unsigned int removed_attrs = 0;
 	int ret;
+	int (*callback)(struct ldb_request *req, struct ldb_reply *ares) = replmd_op_callback;
 
 	ldb = ldb_module_get_ctx(ar->module);
 	msg = ar->objs->objects[ar->index_current].msg;
+
 	rmd = ar->objs->objects[ar->index_current].meta_data;
 	ZERO_STRUCT(omd);
 	omd.version = 1;
@@ -4025,7 +4028,45 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar)
 
 	/* handle renames that come in over DRS */
 	ret = replmd_replicated_handle_rename(ar, msg, rmd, &omd, ar->req);
-	if (ret != LDB_SUCCESS) {
+
+	/*
+	 * This particular error code means that we already tried the
+	 * conflict algrorithm, and the existing record name was newer, so we
+	 * need to rename the incoming record
+	 */
+	if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
+		struct GUID guid;
+		NTSTATUS status;
+		struct ldb_dn *new_dn;
+		status = GUID_from_ndr_blob(&ar->objs->objects[ar->index_current].guid_value, &guid);
+		/* This really, really can't fail */
+		SMB_ASSERT(NT_STATUS_IS_OK(status));
+
+		new_dn = replmd_conflict_dn(msg, msg->dn, &guid);
+		if (new_dn == NULL) {
+			ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
+								  "Failed to form conflict DN for %s\n",
+								  ldb_dn_get_linearized(msg->dn));
+
+			return replmd_replicated_request_werror(ar, WERR_NOMEM);
+		}
+
+		ret = dsdb_module_rename(ar->module, ar->search_msg->dn, new_dn,
+					 DSDB_FLAG_NEXT_MODULE, ar->req);
+		if (ret != LDB_SUCCESS) {
+			ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
+					       "Failed to rename incoming conflicting dn '%s' (was '%s') to '%s' - %s\n",
+					       ldb_dn_get_linearized(msg->dn),
+					       ldb_dn_get_linearized(ar->search_msg->dn),
+					       ldb_dn_get_linearized(new_dn),
+					       ldb_errstring(ldb_module_get_ctx(ar->module)));
+			return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
+		}
+
+		/* Set the callback to one that will fix up the name to be a conflict DN */
+		callback = replmd_op_name_modify_callback;
+		msg->dn = new_dn;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list