[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Tue Jul 30 04:55:04 MDT 2013


The branch, master has been updated
       via  7615b25 samba-tool dbcheck: Correctly remove deleted DNs in dbcheck
       via  f2afdb6 dsdb: Include MS-ADTS doc references on deleted object contstraints
       via  a9e565a dsdb tests: Add member/memberOf checking to delete_objects testing
       via  0162be3 dsdb: Improve DRS deleted link source/target handing in repl_meta_data
       via  32955a1 dsdb: Ensure we always force deleted objects back under the deleted objects DN
       via  a796cad dsdb/repl_meta_data: split out replmd_deletion_state()
       via  d3aad89 dsdb: Prune deleted objects of links and extra attributes of replicated deletes
      from  8f8e843 s3:winbind: add a warning DEBUG message when skipping a sid from the mapped GID list

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


- Log -----------------------------------------------------------------
commit 7615b2549d9549683978cb3e85b926e2ba63e294
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Sun Apr 14 13:32:49 2013 +1000

    samba-tool dbcheck: Correctly remove deleted DNs in dbcheck
    
    The previous pattern never matched, as it was a typo.
    
    Andrew Bartlett
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Tue Jul 30 12:55:00 CEST 2013 on sn-devel-104

commit f2afdb61698c37389be286f9443471d4aeba49b8
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jun 4 20:22:31 2013 +1000

    dsdb: Include MS-ADTS doc references on deleted object contstraints
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit a9e565a5a4478f7b923f35311e170de2044ff848
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Jun 3 17:51:41 2013 +1000

    dsdb tests: Add member/memberOf checking to delete_objects testing
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit 0162be32ab4f9716a4300d1f1a0caae8b0133f7c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jun 4 19:57:06 2013 +1000

    dsdb: Improve DRS deleted link source/target handing in repl_meta_data
    
    We now correctly ignore the link updates if the source or target is
    deleted locally.
    
    This fixes the long-standing failure in the vampire_dc dbcheck test.
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Andrew Bartlett
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit 32955a1dec3a97ab4550869dbeb5034247f3b1bc
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Jun 17 22:37:20 2013 +1000

    dsdb: Ensure we always force deleted objects back under the deleted objects DN
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit a796cad90f1028ccc54a3539e34dc0728b990a96
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 5 09:35:42 2013 +0200

    dsdb/repl_meta_data: split out replmd_deletion_state()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d3aad891c5759f66bd891cb47866d908a0562a8a
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri May 31 20:01:17 2013 +1000

    dsdb: Prune deleted objects of links and extra attributes of replicated deletes
    
    When an object is deleted, the links to be removed are not propogated,
    you have to watch out for them manually!
    
    We do this by calling back into the originating update delete code (ie
    what is called if you ldb_delete() locally) so that any extra
    attribute found locally and not on the remote server becomes removed
    remotely too.
    
    We currently do the same with links, but that isn't strictly correct,
    but for now our getNCChanges server code filters these out, so only
    the usn is bumped.
    
    Andrew Bartlett
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

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

Summary of changes:
 python/samba/dbchecker.py                       |    2 +-
 selftest/knownfail                              |    1 -
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c |  568 ++++++++++++++++++-----
 source4/torture/drs/python/delete_object.py     |  278 ++++++++++-
 4 files changed, 698 insertions(+), 151 deletions(-)


Changeset truncated at 500 lines:

diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index e88f876..8b175c2 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -271,7 +271,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
         """handle a missing target DN (both GUID and DN string form are missing)"""
         # check if its a backlink
         linkID = self.samdb_schema.get_linkId_from_lDAPDisplayName(attrname)
-        if (linkID & 1 == 0) and str(dsdb_dn).find('DEL\\0A') == -1:
+        if (linkID & 1 == 0) and str(dsdb_dn).find('\\0ADEL') == -1:
             self.report("Not removing dangling forward link")
             return
         self.err_deleted_dn(dn, attrname, val, dsdb_dn, dsdb_dn)
diff --git a/selftest/knownfail b/selftest/knownfail
index 4fe96f3..0c501fa 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -176,7 +176,6 @@
 ^samba4.ntvfs.cifs.krb5.base.createx_access.createx_access\(.*\)$
 ^samba4.rpc.lsa.forest.trust #Not fully provided by Samba4
 ^samba4.blackbox.kinit\(.*\).kinit with user password for expired password\(.*\) # We need to work out why this fails only during the pw change
-^samba4.blackbox.dbcheck\(vampire_dc\).dbcheck\(vampire_dc:local\) # Due to replicating with --domain-critical-only we fail dbcheck on this database
 ^samba4.blackbox.upgradeprovision.alpha13.ldapcmp_sd\(none\) # Due to something rewriting the NT ACL on DNS objects
 ^samba4.blackbox.upgradeprovision.alpha13.ldapcmp_full_sd\(none\) # Due to something rewriting the NT ACL on DNS objects
 ^samba4.blackbox.upgradeprovision.release-4-0-0.ldapcmp_sd\(none\) # Due to something rewriting the NT ACL on DNS objects
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index b6ff7ff..c8cdfec 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -2,10 +2,10 @@
    ldb database library
 
    Copyright (C) Simo Sorce  2004-2008
-   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2005
-   Copyright (C) Andrew Tridgell 2005
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2005-2013
+   Copyright (C) Andrew Tridgell 2005-2009
    Copyright (C) Stefan Metzmacher <metze at samba.org> 2007
-   Copyright (C) Matthieu Patou <mat at samba.org> 2010
+   Copyright (C) Matthieu Patou <mat at samba.org> 2010-2011
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -92,9 +92,12 @@ struct replmd_replicated_request {
 
 	uint64_t seq_num;
 	bool is_urgent;
+
+	bool isDeleted;
 };
 
 static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar);
+static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete);
 
 enum urgent_situation {
 	REPL_URGENT_ON_CREATE = 1,
@@ -102,6 +105,70 @@ enum urgent_situation {
 	REPL_URGENT_ON_DELETE = 4
 };
 
+enum deletion_state {
+	OBJECT_NOT_DELETED=1,
+	OBJECT_DELETED=2,
+	OBJECT_RECYCLED=3,
+	OBJECT_TOMBSTONE=4,
+	OBJECT_REMOVED=5
+};
+
+static void replmd_deletion_state(struct ldb_module *module,
+				  const struct ldb_message *msg,
+				  enum deletion_state *current_state,
+				  enum deletion_state *next_state)
+{
+	int ret;
+	bool enabled = false;
+
+	if (msg == NULL) {
+		*current_state = OBJECT_REMOVED;
+		if (next_state != NULL) {
+			*next_state = OBJECT_REMOVED;
+		}
+		return;
+	}
+
+	ret = dsdb_recyclebin_enabled(module, &enabled);
+	if (ret != LDB_SUCCESS) {
+		enabled = false;
+	}
+
+	if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) {
+		if (!enabled) {
+			*current_state = OBJECT_TOMBSTONE;
+			if (next_state != NULL) {
+				*next_state = OBJECT_REMOVED;
+			}
+			return;
+		}
+
+		if (ldb_msg_check_string_attribute(msg, "isRecycled", "TRUE")) {
+			*current_state = OBJECT_RECYCLED;
+			if (next_state != NULL) {
+				*next_state = OBJECT_REMOVED;
+			}
+			return;
+		}
+
+		*current_state = OBJECT_DELETED;
+		if (next_state != NULL) {
+			*next_state = OBJECT_RECYCLED;
+		}
+		return;
+	}
+
+	*current_state = OBJECT_NOT_DELETED;
+	if (next_state == NULL) {
+		return;
+	}
+
+	if (enabled) {
+		*next_state = OBJECT_DELETED;
+	} else {
+		*next_state = OBJECT_TOMBSTONE;
+	}
+}
 
 static const struct {
 	const char *update_name;
@@ -154,7 +221,7 @@ static bool replmd_check_urgent_attribute(const struct ldb_message_element *el)
 }
 
 
-static int replmd_replicated_apply_next(struct replmd_replicated_request *ar);
+static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar);
 
 /*
   initialise the module
@@ -456,10 +523,7 @@ static int replmd_op_callback(struct ldb_request *req, struct ldb_reply *ares)
 	}
 
 	if (ac->apply_mode) {
-		talloc_free(ares);
-		ac->index_current++;
-
-		ret = replmd_replicated_apply_next(ac);
+		ret = replmd_replicated_apply_isDeleted(ac);
 		if (ret != LDB_SUCCESS) {
 			return ldb_module_done(ac->req, NULL, NULL, ret);
 		}
@@ -2735,8 +2799,11 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are
 }
 
 /*
-   remove links from objects that point at this object when an object
-   is deleted
+ * remove links from objects that point at this object when an object
+ * is deleted.  We remove it from the NEXT module per MS-DRSR 5.160
+ * RemoveObj which states that link removal due to the object being
+ * deleted is NOT an originating update - they just go away!
+ *
  */
 static int replmd_delete_remove_link(struct ldb_module *module,
 				     const struct dsdb_schema *schema,
@@ -2817,8 +2884,13 @@ static int replmd_delete_remove_link(struct ldb_module *module,
 
   This also handles the mapping of delete to a rename operation
   to allow deletes to be replicated.
+
+  It also handles the incoming deleted objects, to ensure they are
+  fully deleted here.  In that case re_delete is true, and we do not
+  use this as a signal to change the deleted state, just reinforce it.
+
  */
-static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
+static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete)
 {
 	int ret = LDB_ERR_OTHER;
 	bool retb, disallow_move_on_delete;
@@ -2844,10 +2916,7 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 		"trustType", "trustAttributes", "userAccountControl", "uSNChanged", "uSNCreated", "whenCreated",
 		"whenChanged", NULL};
 	unsigned int i, el_count = 0;
-	enum deletion_state { OBJECT_NOT_DELETED=1, OBJECT_DELETED=2, OBJECT_RECYCLED=3,
-						OBJECT_TOMBSTONE=4, OBJECT_REMOVED=5 };
 	enum deletion_state deletion_state, next_deletion_state;
-	bool enabled;
 
 	if (ldb_dn_is_special(req->op.del.dn)) {
 		return ldb_next_request(module, req);
@@ -2861,6 +2930,7 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 
 	schema = dsdb_get_schema(ldb, tmp_ctx);
 	if (!schema) {
+		talloc_free(tmp_ctx);
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
@@ -2874,36 +2944,24 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 				    DSDB_SEARCH_REVEAL_INTERNALS |
 				    DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req);
 	if (ret != LDB_SUCCESS) {
+		ldb_asprintf_errstring(ldb_module_get_ctx(module),
+				       "repmd_delete: Failed to %s %s, because we failed to find it: %s",
+				       re_delete ? "re-delete" : "delete",
+				       ldb_dn_get_linearized(old_dn),
+				       ldb_errstring(ldb_module_get_ctx(module)));
 		talloc_free(tmp_ctx);
 		return ret;
 	}
 	old_msg = res->msgs[0];
 
+	replmd_deletion_state(module, old_msg,
+			      &deletion_state,
+			      &next_deletion_state);
 
-	ret = dsdb_recyclebin_enabled(module, &enabled);
-	if (ret != LDB_SUCCESS) {
-		talloc_free(tmp_ctx);
-		return ret;
-	}
-
-	if (ldb_msg_check_string_attribute(old_msg, "isDeleted", "TRUE")) {
-		if (!enabled) {
-			deletion_state = OBJECT_TOMBSTONE;
-			next_deletion_state = OBJECT_REMOVED;
-		} else if (ldb_msg_check_string_attribute(old_msg, "isRecycled", "TRUE")) {
-			deletion_state = OBJECT_RECYCLED;
-			next_deletion_state = OBJECT_REMOVED;
-		} else {
-			deletion_state = OBJECT_DELETED;
-			next_deletion_state = OBJECT_RECYCLED;
-		}
-	} else {
-		deletion_state = OBJECT_NOT_DELETED;
-		if (enabled) {
-			next_deletion_state = OBJECT_DELETED;
-		} else {
-			next_deletion_state = OBJECT_TOMBSTONE;
-		}
+	/* This supports us noticing an incoming isDeleted and acting on it */
+	if (re_delete) {
+		SMB_ASSERT(deletion_state > OBJECT_NOT_DELETED);
+		next_deletion_state = deletion_state;
 	}
 
 	if (next_deletion_state == OBJECT_REMOVED) {
@@ -2936,45 +2994,57 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 
 	msg->dn = old_dn;
 
-	if (deletion_state == OBJECT_NOT_DELETED){
-		/* consider the SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE flag */
-		disallow_move_on_delete =
-			(ldb_msg_find_attr_as_int(old_msg, "systemFlags", 0)
-				& SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
+	/* consider the SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE flag */
+	disallow_move_on_delete =
+		(ldb_msg_find_attr_as_int(old_msg, "systemFlags", 0)
+		 & SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
 
-		/* work out where we will be renaming this object to */
-		if (!disallow_move_on_delete) {
-			ret = dsdb_get_deleted_objects_dn(ldb, tmp_ctx, old_dn,
-							  &new_dn);
-			if (ret != LDB_SUCCESS) {
-				/* this is probably an attempted delete on a partition
-				 * that doesn't allow delete operations, such as the
-				 * schema partition */
-				ldb_asprintf_errstring(ldb, "No Deleted Objects container for DN %s",
-							   ldb_dn_get_linearized(old_dn));
-				talloc_free(tmp_ctx);
-				return LDB_ERR_UNWILLING_TO_PERFORM;
-			}
-		} else {
+	/* work out where we will be renaming this object to */
+	if (!disallow_move_on_delete) {
+		ret = dsdb_get_deleted_objects_dn(ldb, tmp_ctx, old_dn,
+						  &new_dn);
+		/*
+		 * Deleted Objects itself appears to be deleted, but
+		 * should also not be moved, and we should not move
+		 * objects if we can't find the deleted objects DN
+		 */
+		if (re_delete && (ret != LDB_SUCCESS || ldb_dn_compare(old_dn, new_dn) == 0)) {
 			new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
 			if (new_dn == NULL) {
 				ldb_module_oom(module);
 				talloc_free(tmp_ctx);
 				return LDB_ERR_OPERATIONS_ERROR;
 			}
+		} else if (ret != LDB_SUCCESS) {
+			/* this is probably an attempted delete on a partition
+			 * that doesn't allow delete operations, such as the
+			 * schema partition */
+			ldb_asprintf_errstring(ldb, "No Deleted Objects container for DN %s",
+					       ldb_dn_get_linearized(old_dn));
+			talloc_free(tmp_ctx);
+			return LDB_ERR_UNWILLING_TO_PERFORM;
 		}
+	} else {
+		new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
+		if (new_dn == NULL) {
+			ldb_module_oom(module);
+			talloc_free(tmp_ctx);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+	}
 
+	if (deletion_state == OBJECT_NOT_DELETED) {
 		/* get the objects GUID from the search we just did */
 		guid = samdb_result_guid(old_msg, "objectGUID");
 
 		/* Add a formatted child */
 		retb = ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ADEL:%s",
-						rdn_name,
-						ldb_dn_escape_value(tmp_ctx, *rdn_value),
-						GUID_string(tmp_ctx, &guid));
+					    rdn_name,
+					    ldb_dn_escape_value(tmp_ctx, *rdn_value),
+					    GUID_string(tmp_ctx, &guid));
 		if (!retb) {
 			DEBUG(0,(__location__ ": Unable to add a formatted child to dn: %s",
-					ldb_dn_get_linearized(new_dn)));
+				 ldb_dn_get_linearized(new_dn)));
 			talloc_free(tmp_ctx);
 			return LDB_ERR_OPERATIONS_ERROR;
 		}
@@ -2987,6 +3057,30 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 			return ret;
 		}
 		msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
+	} else {
+		/*
+		 * No matter what has happened with other renames etc, try again to
+		 * get this to be under the deleted DN. See MS-DRSR 5.160 RemoveObj
+		 */
+
+		struct ldb_dn *rdn = ldb_dn_copy(tmp_ctx, old_dn);
+		retb = ldb_dn_remove_base_components(rdn, ldb_dn_get_comp_num(rdn) - 1);
+		if (!retb) {
+			DEBUG(0,(__location__ ": Unable to add a prepare rdn of %s",
+				 ldb_dn_get_linearized(rdn)));
+			talloc_free(tmp_ctx);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+		SMB_ASSERT(ldb_dn_get_comp_num(rdn) == 1);
+
+		retb = ldb_dn_add_child(new_dn, rdn);
+		if (!retb) {
+			DEBUG(0,(__location__ ": Unable to add rdn %s to base dn: %s",
+				 ldb_dn_get_linearized(rdn),
+				 ldb_dn_get_linearized(new_dn)));
+			talloc_free(tmp_ctx);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
 	}
 
 	/*
@@ -3006,63 +3100,64 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 	  see MS-ADTS "Tombstone Requirements" section 3.1.1.5.5.1.1
 	 */
 
-	/* we need the storage form of the parent GUID */
-	ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res,
-				    ldb_dn_get_parent(tmp_ctx, old_dn), NULL,
-				    DSDB_FLAG_NEXT_MODULE |
-				    DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
-				    DSDB_SEARCH_REVEAL_INTERNALS|
-				    DSDB_SEARCH_SHOW_RECYCLED, req);
-	if (ret != LDB_SUCCESS) {
-		talloc_free(tmp_ctx);
-		return ret;
-	}
-
-	if (deletion_state == OBJECT_NOT_DELETED){
-		ret = ldb_msg_add_steal_string(msg, "lastKnownParent",
-						   ldb_dn_get_extended_linearized(tmp_ctx, parent_res->msgs[0]->dn, 1));
+	if (deletion_state == OBJECT_NOT_DELETED) {
+		/* we need the storage form of the parent GUID */
+		ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res,
+					    ldb_dn_get_parent(tmp_ctx, old_dn), NULL,
+					    DSDB_FLAG_NEXT_MODULE |
+					    DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
+					    DSDB_SEARCH_REVEAL_INTERNALS|
+					    DSDB_SEARCH_SHOW_RECYCLED, req);
 		if (ret != LDB_SUCCESS) {
-			DEBUG(0,(__location__ ": Failed to add lastKnownParent string to the msg\n"));
-			ldb_module_oom(module);
+			ldb_asprintf_errstring(ldb_module_get_ctx(module),
+					       "repmd_delete: Failed to %s %s, because we failed to find it's parent (%s): %s",
+					       re_delete ? "re-delete" : "delete",
+					       ldb_dn_get_linearized(old_dn),
+					       ldb_dn_get_linearized(ldb_dn_get_parent(tmp_ctx, old_dn)),
+					       ldb_errstring(ldb_module_get_ctx(module)));
 			talloc_free(tmp_ctx);
 			return ret;
 		}
-		msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
-	}
 
-	switch (next_deletion_state){
-
-	case OBJECT_DELETED:
-
-		ret = ldb_msg_add_value(msg, "msDS-LastKnownRDN", rdn_value, NULL);
+		ret = ldb_msg_add_steal_string(msg, "lastKnownParent",
+						   ldb_dn_get_extended_linearized(tmp_ctx, parent_res->msgs[0]->dn, 1));
 		if (ret != LDB_SUCCESS) {
-			DEBUG(0,(__location__ ": Failed to add msDS-LastKnownRDN string to the msg\n"));
+			DEBUG(0,(__location__ ": Failed to add lastKnownParent string to the msg\n"));
 			ldb_module_oom(module);
 			talloc_free(tmp_ctx);
 			return ret;
 		}
-		msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD;
-
-		ret = ldb_msg_add_empty(msg, "objectCategory", LDB_FLAG_MOD_REPLACE, NULL);
-		if (ret != LDB_SUCCESS) {
-			talloc_free(tmp_ctx);
-			ldb_module_oom(module);
-			return ret;
-		}
+		msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
 
-		ret = ldb_msg_add_empty(msg, "sAMAccountType", LDB_FLAG_MOD_REPLACE, NULL);
-		if (ret != LDB_SUCCESS) {
-			talloc_free(tmp_ctx);
-			ldb_module_oom(module);
-			return ret;
+		if (next_deletion_state == OBJECT_DELETED) {
+			ret = ldb_msg_add_value(msg, "msDS-LastKnownRDN", rdn_value, NULL);
+			if (ret != LDB_SUCCESS) {
+				DEBUG(0,(__location__ ": Failed to add msDS-LastKnownRDN string to the msg\n"));
+				ldb_module_oom(module);
+				talloc_free(tmp_ctx);
+				return ret;
+			}
+			msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD;
 		}
+	}
 
-		break;
+	switch (next_deletion_state) {
 
 	case OBJECT_RECYCLED:
 	case OBJECT_TOMBSTONE:
 
 		/*
+		 * MS-ADTS 3.1.1.5.5.1.1 Tombstone Requirements
+		 * describes what must be removed from a tombstone
+		 * object
+		 *
+		 * MS-ADTS 3.1.1.5.5.1.3 Recycled-Object Requirements
+		 * describes what must be removed from a recycled
+		 * object
+		 *
+		 */
+
+		/*
 		 * we also mark it as recycled, meaning this object can't be
 		 * recovered (we are stripping its attributes).
 		 * This is done only if we have this schema object of course ...
@@ -3078,7 +3173,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;
 		}
 
 		/* work out which of the old attributes we will be removing */
@@ -3124,6 +3219,41 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
 				return ret;
 			}
 		}
+
+		/* Duplicate with the below - we remove the
+		 * samAccountType as an originating update, in case it
+		 * somehow came back.  The objectCategory will have
+		 * gone in the above */
+		ret = ldb_msg_add_empty(msg, "sAMAccountType", LDB_FLAG_MOD_REPLACE, NULL);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			ldb_module_oom(module);
+			return ret;
+		}
+
+		break;
+
+	case OBJECT_DELETED:
+		/*
+		 * MS-ADTS 3.1.1.5.5.1.2 Deleted-Object Requirements
+		 * describes what must be removed from a deleted
+		 * object
+		 */
+
+		ret = ldb_msg_add_empty(msg, "objectCategory", LDB_FLAG_MOD_REPLACE, NULL);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			ldb_module_oom(module);
+			return ret;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list