1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00

r25723: 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
(This used to be commit 10ba3ae699)
This commit is contained in:
Andrew Bartlett 2007-10-25 05:04:55 +02:00 committed by Stefan Metzmacher
parent b28810ab94
commit 1f680ef45d

View File

@ -42,6 +42,8 @@ struct subtree_rename_context {
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 @@ static int subtree_rename_search_callback(struct ldb_context *ldb, void *context
/* 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 @@ static int subtree_rename(struct ldb_module *module, struct ldb_request *req)
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 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,
};