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,
 };
 

Reply via email to