svn commit: samba r25723 - in branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules: .

abartlet at samba.org abartlet at samba.org
Thu Oct 25 05:04:55 GMT 2007


Author: abartlet
Date: 2007-10-25 05:04:55 +0000 (Thu, 25 Oct 2007)
New Revision: 25723

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=25723

Log:
Add a check to prevent deletion of entries with children.  Sadly MMC
doesn't trigger it's recursive delete correctly, but the error return
is correct (but perhaps needs a different LDAP wire format).

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/subtree_rename.c


Changeset:
Modified: branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/subtree_rename.c
===================================================================
--- branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/subtree_rename.c	2007-10-24 19:16:10 UTC (rev 25722)
+++ branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/subtree_rename.c	2007-10-25 05:04:55 UTC (rev 25723)
@@ -42,6 +42,8 @@
 	struct ldb_request **down_req;
 	int num_requests;
 	int finished_requests;
+
+	int num_children;
 };
 
 static struct subtree_rename_context *subtree_rename_init_handle(struct ldb_request *req, 
@@ -95,7 +97,7 @@
 
 	/* Only entries are interesting, and we handle the case of the parent seperatly */
 	if (ares->type == LDB_REPLY_ENTRY
-	    && ldb_dn_compare(ares->message->dn, ac->orig_req->op.rename.olddn) != 0) {
+	    && ldb_dn_compare(ares->message->dn, ac->orig_req->op.rename.olddn) == 0) {
 		/* And it is an actual entry: now create a rename from it */
 		int ret;
 
@@ -203,6 +205,114 @@
 	return ldb_next_request(module, new_req);
 }
 
+
+static int subtree_delete_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) 
+{
+	struct ldb_request *req;
+	struct subtree_rename_context *ac = talloc_get_type(context, struct subtree_rename_context);
+	TALLOC_CTX *mem_ctx = talloc_new(ac);
+    
+	if (!mem_ctx) {
+		ldb_oom(ac->module->ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	/* OK, we have one of *many* search results here:
+
+	   We should also get the entry we tried to rename.  This
+	   callback handles this and everything below it.
+	 */
+
+	/* Only entries are interesting, and we handle the case of the parent seperatly */
+	if (ares->type == LDB_REPLY_ENTRY
+	    && ldb_dn_compare(ares->message->dn, ac->orig_req->op.del.dn) != 0) {
+		/* And it is an actual entry: now object bitterly that we are not a leaf node */
+		ac->num_children++;
+		talloc_free(ares);
+		return LDB_SUCCESS;
+	} else if (ares->type == LDB_REPLY_DONE) {
+		talloc_free(ares);
+		if (ac->num_children > 0) {
+			ldb_asprintf_errstring(ac->module->ldb, "Cannot delete %s, not a leaf node (has %d children)\n",
+					    ldb_dn_get_linearized(ac->orig_req->op.del.dn), ac->num_children);
+			return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF;
+		} else {
+			req = talloc(mem_ctx, struct ldb_request);
+			if (!req) {
+				ldb_oom(ac->module->ldb);
+				return LDB_ERR_OPERATIONS_ERROR;
+			}
+			*req = *ac->orig_req;
+			
+			ac->down_req = talloc_realloc(ac, ac->down_req, 
+						      struct ldb_request *, ac->num_requests + 1);
+			if (!ac->down_req) {
+				ldb_oom(ac->module->ldb);
+				return LDB_ERR_OPERATIONS_ERROR;
+			}
+			ac->down_req[ac->num_requests] = req;
+			ac->num_requests++;
+			
+			return ldb_next_request(ac->module, req);
+		}
+	} else {
+		talloc_free(ares);
+		return LDB_SUCCESS;
+	}
+}
+
+/* rename */
+static int subtree_delete(struct ldb_module *module, struct ldb_request *req)
+{
+	const char *attrs[] = { NULL };
+	struct ldb_request *new_req;
+	struct subtree_rename_context *ac;
+	int ret;
+	if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */
+		return ldb_next_request(module, req);
+	}
+
+	/* This gets complex:  We need to:
+	   - Do a search for all entires under this entry 
+	   - Wait for these results to appear
+	   - In the callback for each result, issue a modify request
+	    - That will include this rename, we hope
+	   - Wait for each modify result
+	   - Regain our sainity 
+	*/
+
+	ac = subtree_rename_init_handle(req, module);
+	if (!ac) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	ret = ldb_build_search_req(&new_req, module->ldb, req,
+				   req->op.del.dn, 
+				   LDB_SCOPE_SUBTREE,
+				   "(objectClass=*)",
+				   attrs,
+				   req->controls,
+				   ac, 
+				   subtree_delete_search_callback);
+
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	ac->down_req = talloc_realloc(ac, ac->down_req, 
+					struct ldb_request *, ac->num_requests + 1);
+	if (!ac->down_req) {
+		ldb_oom(ac->module->ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	ac->down_req[ac->num_requests] = new_req;
+	if (req == NULL) {
+		ldb_oom(ac->module->ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	ac->num_requests++;
+	return ldb_next_request(module, new_req);
+}
+
 static int subtree_rename_wait_none(struct ldb_handle *handle) {
 	struct subtree_rename_context *ac;
 	int i, ret = LDB_ERR_OPERATIONS_ERROR;
@@ -268,6 +378,7 @@
 static const struct ldb_module_ops subtree_rename_ops = {
 	.name		   = "subtree_rename",
 	.rename            = subtree_rename,
+	.del               = subtree_delete,
 	.wait              = subtree_rename_wait,
 };
 



More information about the samba-cvs mailing list