summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/config.mk13
-rw-r--r--source4/dsdb/samdb/ldb_modules/linked_attributes.c68
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectclass.c29
-rw-r--r--source4/dsdb/samdb/ldb_modules/pdc_fsmo.c7
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_fsmo.c7
-rw-r--r--source4/dsdb/samdb/ldb_modules/subtree_delete.c255
-rw-r--r--source4/dsdb/samdb/ldb_modules/subtree_rename.c132
7 files changed, 348 insertions, 163 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk
index 808fb58048..3c43d47cef 100644
--- a/source4/dsdb/samdb/ldb_modules/config.mk
+++ b/source4/dsdb/samdb/ldb_modules/config.mk
@@ -265,6 +265,19 @@ OBJ_FILES = \
################################################
################################################
+# Start MODULE ldb_subtree_rename
+[MODULE::ldb_subtree_delete]
+INIT_FUNCTION = ldb_subtree_delete_init
+OUTPUT_TYPE = SHARED_LIBRARY
+CFLAGS = -Ilib/ldb/include
+PRIVATE_DEPENDENCIES = LIBTALLOC
+SUBSYSTEM = LIBLDB
+OBJ_FILES = \
+ subtree_delete.o
+# End MODULE ldb_subtree_rename
+################################################
+
+################################################
# Start MODULE ldb_linked_attributes
[MODULE::ldb_linked_attributes]
INIT_FUNCTION = ldb_linked_attributes_init
diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
index be5dd12d3b..f3e66c5065 100644
--- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c
+++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
@@ -34,10 +34,12 @@
#include "dsdb/samdb/samdb.h"
struct linked_attributes_context {
+ enum la_step {LA_SEARCH, LA_DO_OPS} step;
struct ldb_module *module;
struct ldb_handle *handle;
struct ldb_request *orig_req;
+ struct ldb_request *search_req;
struct ldb_request **down_req;
int num_requests;
int finished_requests;
@@ -82,7 +84,7 @@ static struct linked_attributes_context *linked_attributes_init_handle(struct ld
static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
struct linked_attributes_context *ac,
- struct ldb_message *msg,
+ const struct ldb_message *msg,
struct ldb_dn *olddn, struct ldb_dn *newdn)
{
int i, j, ret = LDB_SUCCESS;
@@ -192,6 +194,7 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
ac->down_req[ac->num_requests] = new_req;
ac->num_requests++;
+
/* Run the new request */
ret = ldb_next_request(ac->module, new_req);
if (ret != LDB_SUCCESS) {
@@ -272,6 +275,8 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request *
/* Even link IDs are for the originating attribute */
}
+
+ ac->step = LA_DO_OPS;
/* Now call the common routine to setup the modifies across all the attributes */
return setup_modifies(module->ldb, ac, ac, req->op.add.message, NULL, req->op.add.message->dn);
@@ -322,6 +327,8 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques
ac->num_requests++;
+ ac->step = LA_DO_OPS;
+
/* Run the original request */
ret = ldb_next_request(module, ac->down_req[0]);
if (ret != LDB_SUCCESS) {
@@ -539,18 +546,8 @@ static int linked_attributes_rename(struct ldb_module *module, struct ldb_reques
talloc_steal(new_req, attrs);
- 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++;
+ ac->search_req = new_req;
+ ac->step = LA_SEARCH;
return ldb_next_request(module, new_req);
}
@@ -602,18 +599,8 @@ static int linked_attributes_delete(struct ldb_module *module, struct ldb_reques
talloc_steal(new_req, attrs);
- 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++;
+ ac->search_req = new_req;
+ ac->step = LA_SEARCH;
return ldb_next_request(module, new_req);
}
@@ -634,21 +621,42 @@ static int linked_attributes_wait_none(struct ldb_handle *handle) {
ac = talloc_get_type(handle->private_data, struct linked_attributes_context);
- for (i=0; i < ac->num_requests; i++) {
- ret = ldb_wait(ac->down_req[i]->handle, LDB_WAIT_NONE);
+ switch (ac->step) {
+ case LA_SEARCH:
+ ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
if (ret != LDB_SUCCESS) {
handle->status = ret;
goto done;
}
- if (ac->down_req[i]->handle->status != LDB_SUCCESS) {
- handle->status = ac->down_req[i]->handle->status;
+ if (ac->search_req->handle->status != LDB_SUCCESS) {
+ handle->status = ac->search_req->handle->status;
goto done;
}
- if (ac->down_req[i]->handle->state != LDB_ASYNC_DONE) {
+ if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
return LDB_SUCCESS;
}
+ ac->step = LA_DO_OPS;
+ return LDB_SUCCESS;
+
+ case LA_DO_OPS:
+ for (i=0; i < ac->num_requests; i++) {
+ ret = ldb_wait(ac->down_req[i]->handle, LDB_WAIT_NONE);
+
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->down_req[i]->handle->status != LDB_SUCCESS) {
+ handle->status = ac->down_req[i]->handle->status;
+ goto done;
+ }
+
+ if (ac->down_req[i]->handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+ }
}
done:
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index 50ea2ec4e2..5626d9a891 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -68,6 +68,8 @@ struct class_list {
const struct dsdb_class *objectclass;
};
+static int objectclass_do_add(struct ldb_handle *h);
+
static struct ldb_handle *oc_init_handle(struct ldb_request *req, struct ldb_module *module)
{
struct oc_context *ac;
@@ -388,11 +390,17 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
/* return or own handle to deal with this call */
req->handle = h;
- parent_dn = ldb_dn_get_parent(ac, ac->orig_req->op.mod.message->dn);
+ /* If there isn't a parent, just go on to the add processing */
+ if (ldb_dn_get_comp_num(ac->orig_req->op.add.message->dn) == 1) {
+ return objectclass_do_add(h);
+ }
+
+ parent_dn = ldb_dn_get_parent(ac, ac->orig_req->op.add.message->dn);
if (parent_dn == NULL) {
ldb_oom(module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
+
ret = ldb_build_search_req(&ac->search_req, module->ldb,
ac, parent_dn, LDB_SCOPE_BASE,
"(objectClass=*)",
@@ -443,9 +451,7 @@ static int objectclass_do_add(struct ldb_handle *h)
/* Check we have a valid parent */
if (ac->search_res == NULL) {
- if (ldb_dn_get_comp_num(ac->orig_req->op.add.message->dn) <= 1) {
- /* Allow cn=rootdse and cn=templates for now... */
- } else if (ldb_dn_compare(ldb_get_root_basedn(ac->module->ldb), ac->orig_req->op.add.message->dn) == 0) {
+ if (ldb_dn_compare(ldb_get_root_basedn(ac->module->ldb), ac->orig_req->op.add.message->dn) == 0) {
/* Allow the tree to be started */
} else {
ldb_asprintf_errstring(ac->module->ldb, "objectclass: Cannot add %s, parent does not exist!",
@@ -461,6 +467,8 @@ static int objectclass_do_add(struct ldb_handle *h)
&msg->dn);
if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ac->module->ldb, "Could not munge DN %s into normal form",
+ ldb_dn_get_linearized(ac->orig_req->op.add.message->dn));
return ret;
}
@@ -601,7 +609,9 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
switch (objectclass_element->flags & LDB_FLAG_MOD_MASK) {
case LDB_FLAG_MOD_DELETE:
- return LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED;
+ if (objectclass_element->num_values == 0) {
+ return LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED;
+ }
break;
case LDB_FLAG_MOD_REPLACE:
{
@@ -1026,11 +1036,12 @@ static int oc_wait(struct ldb_handle *handle) {
case OC_SEARCH_ADD_PARENT:
ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
- if (ret != LDB_SUCCESS) {
+ if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ret;
goto done;
}
- if (ac->search_req->handle->status != LDB_SUCCESS) {
+ if (ac->search_req->handle->status != LDB_SUCCESS
+ && ac->search_req->handle->status != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ac->search_req->handle->status;
goto done;
}
@@ -1063,11 +1074,11 @@ static int oc_wait(struct ldb_handle *handle) {
case OC_SEARCH_RENAME_PARENT:
ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
- if (ret != LDB_SUCCESS) {
+ if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ret;
goto done;
}
- if (ac->search_req->handle->status != LDB_SUCCESS) {
+ if (ac->search_req->handle->status != LDB_SUCCESS && ac->search_req->handle->status != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ac->search_req->handle->status;
goto done;
}
diff --git a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
index d78ba14ab4..ed9b554bb1 100644
--- a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
@@ -67,7 +67,12 @@ static int pdc_fsmo_init(struct ldb_module *module)
LDB_SCOPE_BASE,
NULL, pdc_attrs,
&pdc_res);
- if (ret != LDB_SUCCESS) {
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+ "pdc_fsmo_init: no domain object present: (skip loading of domain details)");
+ talloc_free(mem_ctx);
+ return ldb_next_init(module);
+ } else if (ret != LDB_SUCCESS) {
ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
"pdc_fsmo_init: failed to search the domain object: %d:%s",
ret, ldb_strerror(ret));
diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
index a92f2646c4..b10e3ac203 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
@@ -90,7 +90,12 @@ static int schema_fsmo_init(struct ldb_module *module)
LDB_SCOPE_BASE,
NULL, schema_attrs,
&schema_res);
- if (ret != LDB_SUCCESS) {
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+ "schema_fsmo_init: no schema head present: (skip schema loading)");
+ talloc_free(mem_ctx);
+ return ldb_next_init(module);
+ } else if (ret != LDB_SUCCESS) {
ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
"schema_fsmo_init: failed to search the schema head: %d:%s",
ret, ldb_strerror(ret));
diff --git a/source4/dsdb/samdb/ldb_modules/subtree_delete.c b/source4/dsdb/samdb/ldb_modules/subtree_delete.c
new file mode 100644
index 0000000000..92f539457e
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/subtree_delete.c
@@ -0,0 +1,255 @@
+/*
+ ldb database library
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
+
+ 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
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldb subtree delete (prevention) module
+ *
+ * Description: Prevent deletion of a subtree in LDB
+ *
+ * Author: Andrew Bartlett
+ */
+
+#include "ldb_includes.h"
+
+struct subtree_delete_context {
+ enum sd_step {SD_SEARCH, SD_DO_DEL} step;
+
+ struct ldb_module *module;
+ struct ldb_handle *handle;
+ struct ldb_request *orig_req;
+
+ struct ldb_request *search_req;
+ struct ldb_request *down_req;
+
+ int num_children;
+};
+
+static struct subtree_delete_context *subtree_delete_init_handle(struct ldb_request *req,
+ struct ldb_module *module)
+{
+ struct subtree_delete_context *ac;
+ struct ldb_handle *h;
+
+ h = talloc_zero(req, struct ldb_handle);
+ if (h == NULL) {
+ ldb_set_errstring(module->ldb, "Out of Memory");
+ return NULL;
+ }
+
+ h->module = module;
+
+ ac = talloc_zero(h, struct subtree_delete_context);
+ if (ac == NULL) {
+ ldb_set_errstring(module->ldb, "Out of Memory");
+ talloc_free(h);
+ return NULL;
+ }
+
+ h->private_data = ac;
+
+ ac->module = module;
+ ac->handle = h;
+ ac->orig_req = req;
+
+ req->handle = h;
+
+ return ac;
+}
+
+static int subtree_delete_check_for_children(struct subtree_delete_context *ac)
+{
+ 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 {
+ struct ldb_request *req = talloc(ac, struct ldb_request);
+ if (!req) {
+ ldb_oom(ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *req = *ac->orig_req;
+
+ ac->down_req = req;
+ ac->step = SD_DO_DEL;
+ return ldb_next_request(ac->module, req);
+ }
+}
+
+static int subtree_delete_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+{
+ struct subtree_delete_context *ac = talloc_get_type(context, struct subtree_delete_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;
+}
+
+/* rename */
+static int subtree_delete(struct ldb_module *module, struct ldb_request *req)
+{
+ const char *attrs[] = { NULL };
+ struct ldb_request *new_req;
+ struct subtree_delete_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, count the children (if any)
+ - return an error if there are any
+ */
+
+ ac = subtree_delete_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->search_req = new_req;
+ if (req == NULL) {
+ ldb_oom(ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ return ldb_next_request(module, new_req);
+}
+
+
+static int subtree_delete_wait_none(struct ldb_handle *handle) {
+ struct subtree_delete_context *ac;
+ int ret = LDB_ERR_OPERATIONS_ERROR;
+ if (!handle || !handle->private_data) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (handle->state == LDB_ASYNC_DONE) {
+ return handle->status;
+ }
+
+ handle->state = LDB_ASYNC_PENDING;
+ handle->status = LDB_SUCCESS;
+
+ ac = talloc_get_type(handle->private_data, struct subtree_delete_context);
+
+ switch (ac->step) {
+ case SD_SEARCH:
+ ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
+
+ if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->search_req->handle->status != LDB_SUCCESS
+ && ac->search_req->handle->status != LDB_ERR_NO_SUCH_OBJECT) {
+ handle->status = ac->search_req->handle->status;
+ goto done;
+ }
+
+ return subtree_delete_check_for_children(ac);
+
+ case SD_DO_DEL:
+ ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE);
+
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->down_req->handle->status != LDB_SUCCESS) {
+ handle->status = ac->down_req->handle->status;
+ goto done;
+ }
+
+ if (ac->down_req->handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ break;
+ }
+done:
+ handle->state = LDB_ASYNC_DONE;
+ return ret;
+}
+
+static int subtree_delete_wait_all(struct ldb_handle *handle) {
+
+ int ret;
+
+ while (handle->state != LDB_ASYNC_DONE) {
+ ret = subtree_delete_wait_none(handle);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ return handle->status;
+}
+
+static int subtree_delete_wait(struct ldb_handle *handle, enum ldb_wait_type type)
+{
+ if (type == LDB_WAIT_ALL) {
+ return subtree_delete_wait_all(handle);
+ } else {
+ return subtree_delete_wait_none(handle);
+ }
+}
+
+static const struct ldb_module_ops subtree_delete_ops = {
+ .name = "subtree_delete",
+ .del = subtree_delete,
+ .wait = subtree_delete_wait,
+};
+
+int ldb_subtree_delete_init(void)
+{
+ return ldb_register_module(&subtree_delete_ops);
+}
diff --git a/source4/dsdb/samdb/ldb_modules/subtree_rename.c b/source4/dsdb/samdb/ldb_modules/subtree_rename.c
index 72857cb864..0964c3fdcd 100644
--- a/source4/dsdb/samdb/ldb_modules/subtree_rename.c
+++ b/source4/dsdb/samdb/ldb_modules/subtree_rename.c
@@ -4,22 +4,18 @@
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
+ 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
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@@ -206,113 +202,6 @@ static int subtree_rename(struct ldb_module *module, struct ldb_request *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;
@@ -378,7 +267,6 @@ static int subtree_rename_wait(struct ldb_handle *handle, enum ldb_wait_type typ
static const struct ldb_module_ops subtree_rename_ops = {
.name = "subtree_rename",
.rename = subtree_rename,
- .del = subtree_delete,
.wait = subtree_rename_wait,
};