From 7c721a1f49d576e0a47c35e465206ade1c05d5a9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 29 Oct 2007 10:54:06 +0100 Subject: r25747: Implement linked attributes, for add operations. Much more work is still required here, particularly to handle this better during the provision, and to handle modifies and deletes, but this is a start. Andrew Bartlett (This used to be commit 2ba99d58e9fe1f8e4b15a58a2fdfce6e876f99b4) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 312 +++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 source4/dsdb/samdb/ldb_modules/linked_attributes.c (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c new file mode 100644 index 0000000000..f386795643 --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -0,0 +1,312 @@ +/* + ldb database library + + Copyright (C) Andrew Bartlett 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 . +*/ + +/* + * Name: ldb + * + * Component: ldb linked_attributes module + * + * Description: Module to ensure linked attribute pairs remain in sync + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" +#include "ldb/include/ldb_private.h" +#include "dsdb/samdb/samdb.h" + +struct linked_attributes_context { + struct ldb_module *module; + struct ldb_handle *handle; + struct ldb_request *orig_req; + + struct ldb_request **down_req; + int num_requests; + int finished_requests; +}; + +static struct linked_attributes_context *linked_attributes_init_handle(struct ldb_request *req, + struct ldb_module *module) +{ + struct linked_attributes_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 linked_attributes_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; +} + +/* add */ +static int linked_attributes_add(struct ldb_module *module, struct ldb_request *req) +{ + int i, j, ret; + struct linked_attributes_context *ac; + + const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); + if (!schema) { + /* without schema, this doesn't make any sense */ + return ldb_next_request(module, req); + } + + if (ldb_dn_is_special(req->op.mod.message->dn)) { + /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + + ac = linked_attributes_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* prepare the first operation */ + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, 1); + if (!ac->down_req) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->down_req[0] = talloc(ac->down_req, struct ldb_request); + if (!ac->down_req[0]) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + *(ac->down_req[0]) = *req; /* copy the request */ + + ac->num_requests++; + + /* Run the original request */ + ret = ldb_next_request(module, req); + if (ret != LDB_SUCCESS) { + return ret; + } + + for (i=0; i < req->op.add.message->num_elements; i++) { + const struct dsdb_attribute *target_attr; + const struct ldb_message_element *el = &req->op.add.message->elements[i]; + const struct dsdb_attribute *schema_attr + = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + if (!schema_attr) { + ldb_asprintf_errstring(module->ldb, + "attribute %s is not a valid attribute in schema", req->op.add.message->elements[i].name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + /* We have a valid attribute, not find out if it is linked */ + if (schema_attr->linkID == 0) { + continue; + } + + if ((schema_attr->linkID & 1) == 1) { + /* Odd is for the target. Illigal to modify */ + ldb_asprintf_errstring(module->ldb, + "attribute %s must not be modified directly, it is a linked attribute", req->op.add.message->elements[i].name); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + /* Even link IDs are for the originating attribute */ + + /* Now find the target attribute */ + target_attr = dsdb_attribute_by_linkID(schema, schema_attr->linkID + 1); + if (!target_attr) { + ldb_asprintf_errstring(module->ldb, + "attribute %s does not have valid link target", req->op.add.message->elements[i].name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + /* Prepare the modify (add element) on the targets */ + + /* For each value being added, we need to setup the modify */ + for (j=0; j < el->num_values; j++) { + struct ldb_request *new_req; + /* Create the modify request */ + struct ldb_message *new_msg = ldb_msg_new(ac->down_req); + if (!new_msg) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data); + if (!new_msg->dn) { + ldb_asprintf_errstring(module->ldb, + "attribute %s value %s was not a valid DN", req->op.add.message->elements[i].name, + el->values[j].data); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, + LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_msg_add_string(new_msg, target_attr->lDAPDisplayName, + ldb_dn_get_linearized(ac->orig_req->op.add.message->dn)); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_mod_req(&new_req, module->ldb, ac->down_req, + new_msg, + NULL, + NULL, + NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(new_req, new_msg); + + ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + /* Now add it to the list */ + 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; + ac->num_requests++; + + /* Run the new request */ + ret = ldb_next_request(module, new_req); + if (ret != LDB_SUCCESS) { + return ret; + } + } + } + return ret; +} + +/* modify */ +static int linked_attributes_modify(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +/* delete */ +static int linked_attributes_delete(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +/* rename */ +static int linked_attributes_rename(struct ldb_module *module, struct ldb_request *req) +{ + return ldb_next_request(module, req); +} + +static int linked_attributes_wait_none(struct ldb_handle *handle) { + struct linked_attributes_context *ac; + int i, 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 linked_attributes_context); + + 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: + handle->state = LDB_ASYNC_DONE; + return ret; + +} + +static int linked_attributes_wait_all(struct ldb_handle *handle) { + + int ret; + + while (handle->state != LDB_ASYNC_DONE) { + ret = linked_attributes_wait_none(handle); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return handle->status; +} + +static int linked_attributes_wait(struct ldb_handle *handle, enum ldb_wait_type type) +{ + if (type == LDB_WAIT_ALL) { + return linked_attributes_wait_all(handle); + } else { + return linked_attributes_wait_none(handle); + } +} + +static const struct ldb_module_ops linked_attributes_ops = { + .name = "linked_attributes", + .add = linked_attributes_add, + .modify = linked_attributes_modify, + .del = linked_attributes_delete, + .rename = linked_attributes_rename, + .wait = linked_attributes_wait, +}; + +int ldb_linked_attributes_init(void) +{ + return ldb_register_module(&linked_attributes_ops); +} -- cgit From 3c5a71f7e5aec48a1a195e5402f7214d481942d2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 31 Oct 2007 05:14:31 +0100 Subject: r25763: Handle modifies, in the easy case (add/delete of elements), for the linked attributes. Andrew Bartlett (This used to be commit c6a6246fbde996ec7e85cb66f060cfe8b90044dd) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 152 ++++++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index f386795643..d3093dbd71 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -220,18 +220,168 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * /* modify */ static int linked_attributes_modify(struct ldb_module *module, struct ldb_request *req) { - return ldb_next_request(module, req); + /* Look over list of modifications */ + /* Find if any are for linked attributes */ + /* Determine the effect of the modification */ + /* Apply the modify to the linked entry */ + + int i, j, ret; + struct linked_attributes_context *ac; + + const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); + if (!schema) { + /* without schema, this doesn't make any sense */ + return ldb_next_request(module, req); + } + + if (ldb_dn_is_special(req->op.mod.message->dn)) { + /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + + ac = linked_attributes_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* prepare the first operation */ + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, 1); + if (!ac->down_req) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->down_req[0] = talloc(ac->down_req, struct ldb_request); + if (!ac->down_req[0]) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + *(ac->down_req[0]) = *req; /* copy the request */ + + ac->num_requests++; + + /* Run the original request */ + ret = ldb_next_request(module, req); + if (ret != LDB_SUCCESS) { + return ret; + } + + for (i=0; i < req->op.mod.message->num_elements; i++) { + const struct dsdb_attribute *target_attr; + const struct ldb_message_element *el = &req->op.mod.message->elements[i]; + const struct dsdb_attribute *schema_attr + = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + if (!schema_attr) { + ldb_asprintf_errstring(module->ldb, + "attribute %s is not a valid attribute in schema", req->op.mod.message->elements[i].name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + /* We have a valid attribute, not find out if it is linked */ + if (schema_attr->linkID == 0) { + continue; + } + + if ((schema_attr->linkID & 1) == 1) { + /* Odd is for the target. Illigal to modify */ + ldb_asprintf_errstring(module->ldb, + "attribute %s must not be modified directly, it is a linked attribute", req->op.mod.message->elements[i].name); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + /* Even link IDs are for the originating attribute */ + + /* Now find the target attribute */ + target_attr = dsdb_attribute_by_linkID(schema, schema_attr->linkID + 1); + if (!target_attr) { + ldb_asprintf_errstring(module->ldb, + "attribute %s does not have valid link target", req->op.mod.message->elements[i].name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + if ((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE) { + ldb_asprintf_errstring(module->ldb, + "attribute %s may not be replaced, only added or deleted", req->op.mod.message->elements[i].name); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + /* Prepare the modify (mod element) on the targets */ + + /* For each value being moded, we need to setup the modify */ + for (j=0; j < el->num_values; j++) { + struct ldb_request *new_req; + /* Create the modify request */ + struct ldb_message *new_msg = ldb_msg_new(ac->down_req); + if (!new_msg) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data); + if (!new_msg->dn) { + ldb_asprintf_errstring(module->ldb, + "attribute %s value %s was not a valid DN", req->op.mod.message->elements[i].name, + el->values[j].data); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, + el->flags & LDB_FLAG_MOD_MASK, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_msg_add_string(new_msg, target_attr->lDAPDisplayName, + ldb_dn_get_linearized(ac->orig_req->op.add.message->dn)); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_mod_req(&new_req, module->ldb, ac->down_req, + new_msg, + NULL, + NULL, + NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(new_req, new_msg); + + ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + /* Now add it to the list */ + 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; + ac->num_requests++; + + /* Run the new request */ + ret = ldb_next_request(module, new_req); + if (ret != LDB_SUCCESS) { + return ret; + } + } + } + return ret; } /* delete */ static int linked_attributes_delete(struct ldb_module *module, struct ldb_request *req) { + /* Look up list of linked attributes */ + /* Search to see if any linked attributes are in this entry */ return ldb_next_request(module, req); } /* rename */ static int linked_attributes_rename(struct ldb_module *module, struct ldb_request *req) { + /* Look up list of linked attributes */ + /* Search to see if any linked attributes are in this entry */ return ldb_next_request(module, req); } -- cgit From 8a8948a17a947bccf04df817f5011093c0c5c523 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Nov 2007 12:34:06 +0100 Subject: r25781: Handle and test linked attribute renames. Andrew Bartlett (This used to be commit 56d9dd5140b6d7d7bbaa2f59ecdff7ee70c4faac) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 317 ++++++++++++++++++++- 1 file changed, 310 insertions(+), 7 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index d3093dbd71..7721296b7c 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -41,6 +41,8 @@ struct linked_attributes_context { struct ldb_request **down_req; int num_requests; int finished_requests; + + const char **linked_attrs; }; static struct linked_attributes_context *linked_attributes_init_handle(struct ldb_request *req, @@ -369,22 +371,323 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques return ret; } -/* delete */ -static int linked_attributes_delete(struct ldb_module *module, struct ldb_request *req) +static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + struct linked_attributes_context *ac, + struct ldb_message *msg, + struct ldb_dn *olddn, struct ldb_dn *newdn) { - /* Look up list of linked attributes */ - /* Search to see if any linked attributes are in this entry */ - return ldb_next_request(module, req); + int i, j, ret = LDB_SUCCESS; + const struct dsdb_schema *schema = dsdb_get_schema(ldb); + /* Look up each of the returned attributes */ + /* Find their schema */ + /* And it is an actual entry: now create a series of modify requests */ + for (i=0; i < msg->num_elements; i++) { + int otherid; + const struct dsdb_attribute *target_attr; + const struct ldb_message_element *el = &msg->elements[i]; + const struct dsdb_attribute *schema_attr + = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + if (!schema_attr) { + ldb_asprintf_errstring(ldb, + "attribute %s is not a valid attribute in schema", el->name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + /* We have a valid attribute, but if it's not linked they maybe we just got an extra return on our search... */ + if (schema_attr->linkID == 0) { + continue; + } + + /* Depending on which direction this link is in, we need to find it's partner */ + if ((schema_attr->linkID & 1) == 1) { + otherid = schema_attr->linkID - 1; + } else { + otherid = schema_attr->linkID + 1; + } + + /* Now find the target attribute */ + target_attr = dsdb_attribute_by_linkID(schema, otherid); + if (!target_attr) { + ldb_asprintf_errstring(ldb, + "attribute %s does not have valid link target", el->name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + /* For each value being moded, we need to setup the modify */ + for (j=0; j < el->num_values; j++) { + struct ldb_message_element *ret_el; + struct ldb_request *new_req; + /* Create the modify request */ + struct ldb_message *new_msg = ldb_msg_new(ac->down_req); + if (!new_msg) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + new_msg->dn = ldb_dn_new(new_msg, ldb, (char *)el->values[j].data); + if (!new_msg->dn) { + ldb_asprintf_errstring(ldb, + "attribute %s value %s was not a valid DN", msg->elements[i].name, + el->values[j].data); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (olddn) { + ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, + LDB_FLAG_MOD_DELETE, &ret_el); + if (ret != LDB_SUCCESS) { + return ret; + } + ret_el->values = talloc_array(new_msg, struct ldb_val, 1); + if (!ret_el->values) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret_el->values[0] = data_blob_string_const(ldb_dn_get_linearized(olddn)); + ret_el->num_values = 1; + } + + if (newdn) { + ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, + LDB_FLAG_MOD_ADD, &ret_el); + if (ret != LDB_SUCCESS) { + return ret; + } + ret_el->values = talloc_array(new_msg, struct ldb_val, 1); + if (!ret_el->values) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret_el->values[0] = data_blob_string_const(ldb_dn_get_linearized(newdn)); + ret_el->num_values = 1; + } + + ret = ldb_build_mod_req(&new_req, ldb, ac->down_req, + new_msg, + NULL, + NULL, + NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(new_req, new_msg); + + ldb_set_timeout_from_prev_req(ldb, ac->orig_req, new_req); + + /* Now add it to the list */ + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, ac->num_requests + 1); + if (!ac->down_req) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + 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) { + return ret; + } + } + } + return ret; } +static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) +{ + struct ldb_request *req; + struct linked_attributes_context *ac = talloc_get_type(context, struct linked_attributes_context); + struct ldb_dn *olddn, *newdn; + TALLOC_CTX *mem_ctx = talloc_new(ac); + + if (!mem_ctx) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + switch (ac->orig_req->operation) { + case LDB_DELETE: + { + olddn = ac->orig_req->op.del.dn; + newdn = NULL; + break; + } + case LDB_RENAME: + { + olddn = ac->orig_req->op.rename.olddn; + newdn = ac->orig_req->op.rename.newdn; + break; + } + default: + return LDB_ERR_OPERATIONS_ERROR; + } + + + /* OK, we have one search result here: */ + + /* Only entries are interesting, and we only want the olddn */ + if (ares->type == LDB_REPLY_ENTRY + && ldb_dn_compare(ares->message->dn, olddn) == 0) { + /* only bother at all if there were some linked attributes found */ + if (ares->message->num_elements > 0) { + return setup_modifies(ldb, mem_ctx, ac, + ares->message, olddn, newdn); + } + talloc_free(ares); + return LDB_SUCCESS; + } else if (ares->type == LDB_REPLY_ENTRY) { + /* Guh? We only asked for this DN */ + return LDB_ERR_OPERATIONS_ERROR; + } else if (ares->type == LDB_REPLY_DONE) { + req = talloc(mem_ctx, struct ldb_request); + *req = *ac->orig_req; + talloc_free(ares); + + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, ac->num_requests + 1); + if (!ac->down_req) { + ldb_oom(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 linked_attributes_rename(struct ldb_module *module, struct ldb_request *req) { /* Look up list of linked attributes */ - /* Search to see if any linked attributes are in this entry */ - return ldb_next_request(module, req); + const char **attrs; + WERROR werr; + int ret; + struct linked_attributes_context *ac; + struct ldb_request *new_req; + const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); + if (!schema) { + /* without schema, this doesn't make any sense */ + return ldb_next_request(module, req); + } + + /* This gets complex: We need to: + - Do a search for the entry + - Wait for these result to appear + - In the callback for the result, issue a modify request based on the linked attributes found + - Wait for each modify result + - Regain our sainity + */ + + ac = linked_attributes_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + werr = dsdb_linked_attribute_lDAPDisplayName_list(schema, ac, &attrs); + if (!W_ERROR_IS_OK(werr)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_build_search_req(&new_req, module->ldb, req, + req->op.rename.olddn, + LDB_SCOPE_BASE, + "(objectClass=*)", + attrs, + NULL, + ac, + linked_attributes_rename_del_search_callback); + + if (ret != LDB_SUCCESS) { + return ret; + } + + 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++; + return ldb_next_request(module, new_req); } +/* delete */ +static int linked_attributes_delete(struct ldb_module *module, struct ldb_request *req) +{ + /* Look up list of linked attributes */ + const char **attrs; + WERROR werr; + int ret; + struct ldb_request *new_req; + struct linked_attributes_context *ac; + const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); + if (!schema) { + /* without schema, this doesn't make any sense */ + return ldb_next_request(module, req); + } + + /* This gets complex: We need to: + - Do a search for the entry + - Wait for these result to appear + - In the callback for the result, issue a modify request based on the linked attributes found + - Wait for each modify result + - Regain our sainity + */ + + ac = linked_attributes_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + werr = dsdb_linked_attribute_lDAPDisplayName_list(schema, ac, &attrs); + if (!W_ERROR_IS_OK(werr)) { + return LDB_ERR_OPERATIONS_ERROR; + }; + + ret = ldb_build_search_req(&new_req, module->ldb, req, + req->op.del.dn, + LDB_SCOPE_BASE, + "(objectClass=*)", + attrs, + NULL, + ac, + linked_attributes_rename_del_search_callback); + + if (ret != LDB_SUCCESS) { + return ret; + } + + 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++; + return ldb_next_request(module, new_req); +} + + static int linked_attributes_wait_none(struct ldb_handle *handle) { struct linked_attributes_context *ac; int i, ret = LDB_ERR_OPERATIONS_ERROR; -- cgit From b98169884b354741318ea1d1768d03215991f77f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 2 Nov 2007 03:39:24 +0100 Subject: r25788: Use a single routine to handle the creation of modify requests in the linked_attributs code. This drasticly reduces the code duplication here. Andrew Bartlett (This used to be commit c66e188e6729a8e12854017d62067b4ae4a23af8) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 334 ++++++++------------- 1 file changed, 132 insertions(+), 202 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index 7721296b7c..aea0a34ec2 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -77,10 +77,135 @@ static struct linked_attributes_context *linked_attributes_init_handle(struct ld return ac; } +/* Common routine to handle reading the attributes and creating a + * series of modify requests */ + +static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + struct linked_attributes_context *ac, + struct ldb_message *msg, + struct ldb_dn *olddn, struct ldb_dn *newdn) +{ + int i, j, ret = LDB_SUCCESS; + const struct dsdb_schema *schema = dsdb_get_schema(ldb); + /* Look up each of the returned attributes */ + /* Find their schema */ + /* And it is an actual entry: now create a series of modify requests */ + for (i=0; i < msg->num_elements; i++) { + int otherid; + const struct dsdb_attribute *target_attr; + const struct ldb_message_element *el = &msg->elements[i]; + const struct dsdb_attribute *schema_attr + = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + if (!schema_attr) { + ldb_asprintf_errstring(ldb, + "attribute %s is not a valid attribute in schema", el->name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + /* We have a valid attribute, but if it's not linked they maybe we just got an extra return on our search... */ + if (schema_attr->linkID == 0) { + continue; + } + + /* Depending on which direction this link is in, we need to find it's partner */ + if ((schema_attr->linkID & 1) == 1) { + otherid = schema_attr->linkID - 1; + } else { + otherid = schema_attr->linkID + 1; + } + + /* Now find the target attribute */ + target_attr = dsdb_attribute_by_linkID(schema, otherid); + if (!target_attr) { + ldb_asprintf_errstring(ldb, + "attribute %s does not have valid link target", el->name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + /* For each value being moded, we need to setup the modify */ + for (j=0; j < el->num_values; j++) { + struct ldb_message_element *ret_el; + struct ldb_request *new_req; + /* Create the modify request */ + struct ldb_message *new_msg = ldb_msg_new(ac->down_req); + if (!new_msg) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + new_msg->dn = ldb_dn_new(new_msg, ldb, (char *)el->values[j].data); + if (!new_msg->dn) { + ldb_asprintf_errstring(ldb, + "attribute %s value %s was not a valid DN", msg->elements[i].name, + el->values[j].data); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + if (olddn) { + ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, + LDB_FLAG_MOD_DELETE, &ret_el); + if (ret != LDB_SUCCESS) { + return ret; + } + ret_el->values = talloc_array(new_msg, struct ldb_val, 1); + if (!ret_el->values) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret_el->values[0] = data_blob_string_const(ldb_dn_get_linearized(olddn)); + ret_el->num_values = 1; + } + + if (newdn) { + ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, + LDB_FLAG_MOD_ADD, &ret_el); + if (ret != LDB_SUCCESS) { + return ret; + } + ret_el->values = talloc_array(new_msg, struct ldb_val, 1); + if (!ret_el->values) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret_el->values[0] = data_blob_string_const(ldb_dn_get_linearized(newdn)); + ret_el->num_values = 1; + } + + ret = ldb_build_mod_req(&new_req, ldb, ac->down_req, + new_msg, + NULL, + NULL, + NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(new_req, new_msg); + + ldb_set_timeout_from_prev_req(ldb, ac->orig_req, new_req); + + /* Now add it to the list */ + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, ac->num_requests + 1); + if (!ac->down_req) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + 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) { + return ret; + } + } + } + return ret; +} + /* add */ static int linked_attributes_add(struct ldb_module *module, struct ldb_request *req) { - int i, j, ret; + int i, ret; struct linked_attributes_context *ac; const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); @@ -123,8 +248,8 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * return ret; } + /* Need to ensure we only have forward links being specified */ for (i=0; i < req->op.add.message->num_elements; i++) { - const struct dsdb_attribute *target_attr; const struct ldb_message_element *el = &req->op.add.message->elements[i]; const struct dsdb_attribute *schema_attr = dsdb_attribute_by_lDAPDisplayName(schema, el->name); @@ -146,77 +271,10 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * } /* Even link IDs are for the originating attribute */ - - /* Now find the target attribute */ - target_attr = dsdb_attribute_by_linkID(schema, schema_attr->linkID + 1); - if (!target_attr) { - ldb_asprintf_errstring(module->ldb, - "attribute %s does not have valid link target", req->op.add.message->elements[i].name); - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - - /* Prepare the modify (add element) on the targets */ - - /* For each value being added, we need to setup the modify */ - for (j=0; j < el->num_values; j++) { - struct ldb_request *new_req; - /* Create the modify request */ - struct ldb_message *new_msg = ldb_msg_new(ac->down_req); - if (!new_msg) { - ldb_oom(module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data); - if (!new_msg->dn) { - ldb_asprintf_errstring(module->ldb, - "attribute %s value %s was not a valid DN", req->op.add.message->elements[i].name, - el->values[j].data); - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - } - - ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, - LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - return ret; - } - - ret = ldb_msg_add_string(new_msg, target_attr->lDAPDisplayName, - ldb_dn_get_linearized(ac->orig_req->op.add.message->dn)); - if (ret != LDB_SUCCESS) { - return ret; - } - - ret = ldb_build_mod_req(&new_req, module->ldb, ac->down_req, - new_msg, - NULL, - NULL, - NULL); - if (ret != LDB_SUCCESS) { - return ret; - } - - talloc_steal(new_req, new_msg); - - ldb_set_timeout_from_prev_req(module->ldb, req, new_req); - - /* Now add it to the list */ - 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; - ac->num_requests++; - - /* Run the new request */ - ret = ldb_next_request(module, new_req); - if (ret != LDB_SUCCESS) { - return ret; - } - } } - return ret; + + /* 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); } /* modify */ @@ -371,140 +429,12 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques return ret; } -static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, - struct linked_attributes_context *ac, - struct ldb_message *msg, - struct ldb_dn *olddn, struct ldb_dn *newdn) -{ - int i, j, ret = LDB_SUCCESS; - const struct dsdb_schema *schema = dsdb_get_schema(ldb); - /* Look up each of the returned attributes */ - /* Find their schema */ - /* And it is an actual entry: now create a series of modify requests */ - for (i=0; i < msg->num_elements; i++) { - int otherid; - const struct dsdb_attribute *target_attr; - const struct ldb_message_element *el = &msg->elements[i]; - const struct dsdb_attribute *schema_attr - = dsdb_attribute_by_lDAPDisplayName(schema, el->name); - if (!schema_attr) { - ldb_asprintf_errstring(ldb, - "attribute %s is not a valid attribute in schema", el->name); - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - /* We have a valid attribute, but if it's not linked they maybe we just got an extra return on our search... */ - if (schema_attr->linkID == 0) { - continue; - } - - /* Depending on which direction this link is in, we need to find it's partner */ - if ((schema_attr->linkID & 1) == 1) { - otherid = schema_attr->linkID - 1; - } else { - otherid = schema_attr->linkID + 1; - } - - /* Now find the target attribute */ - target_attr = dsdb_attribute_by_linkID(schema, otherid); - if (!target_attr) { - ldb_asprintf_errstring(ldb, - "attribute %s does not have valid link target", el->name); - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - - /* For each value being moded, we need to setup the modify */ - for (j=0; j < el->num_values; j++) { - struct ldb_message_element *ret_el; - struct ldb_request *new_req; - /* Create the modify request */ - struct ldb_message *new_msg = ldb_msg_new(ac->down_req); - if (!new_msg) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - new_msg->dn = ldb_dn_new(new_msg, ldb, (char *)el->values[j].data); - if (!new_msg->dn) { - ldb_asprintf_errstring(ldb, - "attribute %s value %s was not a valid DN", msg->elements[i].name, - el->values[j].data); - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - } - - if (olddn) { - ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, - LDB_FLAG_MOD_DELETE, &ret_el); - if (ret != LDB_SUCCESS) { - return ret; - } - ret_el->values = talloc_array(new_msg, struct ldb_val, 1); - if (!ret_el->values) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - ret_el->values[0] = data_blob_string_const(ldb_dn_get_linearized(olddn)); - ret_el->num_values = 1; - } - - if (newdn) { - ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, - LDB_FLAG_MOD_ADD, &ret_el); - if (ret != LDB_SUCCESS) { - return ret; - } - ret_el->values = talloc_array(new_msg, struct ldb_val, 1); - if (!ret_el->values) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - ret_el->values[0] = data_blob_string_const(ldb_dn_get_linearized(newdn)); - ret_el->num_values = 1; - } - - ret = ldb_build_mod_req(&new_req, ldb, ac->down_req, - new_msg, - NULL, - NULL, - NULL); - if (ret != LDB_SUCCESS) { - return ret; - } - - talloc_steal(new_req, new_msg); - - ldb_set_timeout_from_prev_req(ldb, ac->orig_req, new_req); - - /* Now add it to the list */ - ac->down_req = talloc_realloc(ac, ac->down_req, - struct ldb_request *, ac->num_requests + 1); - if (!ac->down_req) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - 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) { - return ret; - } - } - } - return ret; -} - static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) { struct ldb_request *req; struct linked_attributes_context *ac = talloc_get_type(context, struct linked_attributes_context); struct ldb_dn *olddn, *newdn; - TALLOC_CTX *mem_ctx = talloc_new(ac); - if (!mem_ctx) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - switch (ac->orig_req->operation) { case LDB_DELETE: { @@ -530,7 +460,7 @@ static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, && ldb_dn_compare(ares->message->dn, olddn) == 0) { /* only bother at all if there were some linked attributes found */ if (ares->message->num_elements > 0) { - return setup_modifies(ldb, mem_ctx, ac, + return setup_modifies(ldb, ac, ac, ares->message, olddn, newdn); } talloc_free(ares); @@ -539,7 +469,7 @@ static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, /* Guh? We only asked for this DN */ return LDB_ERR_OPERATIONS_ERROR; } else if (ares->type == LDB_REPLY_DONE) { - req = talloc(mem_ctx, struct ldb_request); + req = talloc(ac, struct ldb_request); *req = *ac->orig_req; talloc_free(ares); -- cgit From 27c9f6c235c3c625f4c4e60a73d8f2e86bd4a186 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 7 Nov 2007 05:35:16 +0100 Subject: r25891: Test that we get the correct return value when we attempt to reference invalid entries with a linked attribute. Make Samba4 pass that test, by fixing a silly bug in the linked_attributes module. (By passing down the 'original' request structure, tdb would override our handle, and therefore we would never be called for the 'wait', which collects the errors). Fix up the provision templates to handle the newly required referential integrity. Andrew Bartlett (This used to be commit 0377d85bbdcb2c4f110b0519005f0d1d10bc0c0b) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index aea0a34ec2..be5dd12d3b 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -243,7 +243,7 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * ac->num_requests++; /* Run the original request */ - ret = ldb_next_request(module, req); + ret = ldb_next_request(module, ac->down_req[0]); if (ret != LDB_SUCCESS) { return ret; } @@ -323,7 +323,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques ac->num_requests++; /* Run the original request */ - ret = ldb_next_request(module, req); + ret = ldb_next_request(module, ac->down_req[0]); if (ret != LDB_SUCCESS) { return ret; } -- cgit From 5d4f507a65144d8fe30b3fcd0b9cbcdc088146c6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 13 Nov 2007 22:54:52 +0100 Subject: r25942: Make various ldb modules handle an LDB backend that enforces validity of Base DNs in searches (returning an error of LDB_ERR_NO_SUCH_ENTRY). We need to handle this if ldb_tdb is to behave correctly compared with LDAP, as well as if we are using an LDAP backend. In doing so, I realised that subtree_rename and subtree_delete (prevention) need rather different wait loops, so it seemed easier to split it out into it's own module. I've fixed the licence on both of these modules to be GPLv3. Andrew Bartlett (This used to be commit d3894c90f31fb45e038ab478cd9d7d34962d069b) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 68 ++++++++++++---------- 1 file changed, 38 insertions(+), 30 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') 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: -- cgit From 579eca54b738fb2f78bc994cee8632dbf94c5a2d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 16 Nov 2007 04:18:22 +0100 Subject: r25981: Don't create an ldb_request on NULL. A re-arrangment of the code due to the base DN checking meant that the ac->down_req array wasn't started, so was NULL Andrew Bartlett (This used to be commit 0a44b8e9f3e1a85c27d105cdd1572a0df936f612) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index f3e66c5065..fd36c16d56 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -127,8 +127,18 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, for (j=0; j < el->num_values; j++) { struct ldb_message_element *ret_el; struct ldb_request *new_req; + struct ldb_message *new_msg; + + /* Create a spot in the list for the requests */ + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, ac->num_requests + 1); + if (!ac->down_req) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + /* Create the modify request */ - struct ldb_message *new_msg = ldb_msg_new(ac->down_req); + new_msg = ldb_msg_new(ac->down_req); if (!new_msg) { ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; @@ -184,13 +194,6 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, ldb_set_timeout_from_prev_req(ldb, ac->orig_req, new_req); - /* Now add it to the list */ - ac->down_req = talloc_realloc(ac, ac->down_req, - struct ldb_request *, ac->num_requests + 1); - if (!ac->down_req) { - ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; - } ac->down_req[ac->num_requests] = new_req; ac->num_requests++; -- cgit From 37fdef233e3761d511c624ab79c8ef1587090fba Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 28 Nov 2007 04:24:12 +0100 Subject: r26182: Extend our linked attribute testsuite to cover many more possible modifications, and then extend our implementation to match. Andrew Bartlett (This used to be commit 65d17f0ad7ead438333abcccb0bd56b038ffb88e) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 292 +++++++++++++++------ 1 file changed, 218 insertions(+), 74 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index fd36c16d56..803d24e34e 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -34,19 +34,28 @@ #include "dsdb/samdb/samdb.h" struct linked_attributes_context { - enum la_step {LA_SEARCH, LA_DO_OPS} step; + enum la_step {LA_SEARCH, LA_DO_OPS, LA_DO_ORIG} step; struct ldb_module *module; struct ldb_handle *handle; struct ldb_request *orig_req; struct ldb_request *search_req; struct ldb_request **down_req; + struct ldb_request *orig_down_req; + int num_requests; int finished_requests; const char **linked_attrs; }; +struct replace_context { + struct linked_attributes_context *ac; + struct ldb_message_element *el; +}; + +static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares); + static struct linked_attributes_context *linked_attributes_init_handle(struct ldb_request *req, struct ldb_module *module) { @@ -73,6 +82,14 @@ static struct linked_attributes_context *linked_attributes_init_handle(struct ld ac->module = module; ac->handle = h; ac->orig_req = req; + + ac->orig_down_req = talloc(ac, struct ldb_request); + if (!ac->orig_down_req) { + ldb_oom(ac->module->ldb); + return NULL; + } + + *ac->orig_down_req = *req; req->handle = h; @@ -211,7 +228,7 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, /* add */ static int linked_attributes_add(struct ldb_module *module, struct ldb_request *req) { - int i, ret; + int i; struct linked_attributes_context *ac; const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); @@ -231,29 +248,8 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * return LDB_ERR_OPERATIONS_ERROR; } - /* prepare the first operation */ - ac->down_req = talloc_realloc(ac, ac->down_req, - struct ldb_request *, 1); - if (!ac->down_req) { - ldb_oom(ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - - ac->down_req[0] = talloc(ac->down_req, struct ldb_request); - if (!ac->down_req[0]) { - ldb_oom(ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - *(ac->down_req[0]) = *req; /* copy the request */ - - 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) { - return ret; - } - /* Need to ensure we only have forward links being specified */ for (i=0; i < req->op.add.message->num_elements; i++) { const struct ldb_message_element *el = &req->op.add.message->elements[i]; @@ -279,12 +275,77 @@ 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); } +static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) +{ + struct replace_context *ac2 = talloc_get_type(context, struct replace_context); + struct linked_attributes_context *ac = ac2->ac; + + /* OK, we have one search result here: */ + + /* Only entries are interesting, and we only want the olddn */ + if (ares->type == LDB_REPLY_ENTRY + && ldb_dn_compare(ares->message->dn, ac->orig_req->op.mod.message->dn) == 0) { + /* only bother at all if there were some linked attributes found */ + struct ldb_message_element *search_el + = ldb_msg_find_element(ares->message, + ac2->el->name); + + /* See if this element already exists */ + if (search_el) { + int ret; + struct ldb_message *msg = ldb_msg_new(ac); + if (!msg) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Lazy option: Delete and add the elements on all members */ + msg->num_elements = 1; + msg->elements = search_el; + msg->dn = ac->orig_req->op.mod.message->dn; + + ret = setup_modifies(ac->module->ldb, ac2, ac, msg, ares->message->dn, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + msg->elements = ac2->el; + + ret = setup_modifies(ac->module->ldb, ac2, ac, msg, NULL, ares->message->dn); + if (ret != LDB_SUCCESS) { + return ret; + } + + } else { + /* Looks like it doesn't exist, process like an 'add' */ + struct ldb_message *msg = ldb_msg_new(ac); + if (!msg) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + msg->num_elements = 1; + msg->elements = ac2->el; + msg->dn = ac->orig_req->op.mod.message->dn; + + return setup_modifies(ac->module->ldb, ac2, ac, msg, NULL, ac->orig_req->op.mod.message->dn); + } + talloc_free(ares); + return LDB_SUCCESS; + } else if (ares->type == LDB_REPLY_ENTRY) { + /* Guh? We only asked for this DN */ + return LDB_ERR_OPERATIONS_ERROR; + + } else { + talloc_free(ares); + return LDB_SUCCESS; + } + + +} /* modify */ static int linked_attributes_modify(struct ldb_module *module, struct ldb_request *req) { @@ -293,7 +354,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques /* Determine the effect of the modification */ /* Apply the modify to the linked entry */ - int i, j, ret; + int i, j; struct linked_attributes_context *ac; const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); @@ -314,31 +375,11 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques } /* prepare the first operation */ - ac->down_req = talloc_realloc(ac, ac->down_req, - struct ldb_request *, 1); - if (!ac->down_req) { - ldb_oom(ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - - ac->down_req[0] = talloc(ac->down_req, struct ldb_request); - if (!ac->down_req[0]) { - ldb_oom(ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - *(ac->down_req[0]) = *req; /* copy the request */ - - 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) { - return ret; - } - for (i=0; i < req->op.mod.message->num_elements; i++) { + int ret; + struct ldb_request *new_req; const struct dsdb_attribute *target_attr; const struct ldb_message_element *el = &req->op.mod.message->elements[i]; const struct dsdb_attribute *schema_attr @@ -370,18 +411,109 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques return LDB_ERR_OBJECT_CLASS_VIOLATION; } - if ((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE) { - ldb_asprintf_errstring(module->ldb, - "attribute %s may not be replaced, only added or deleted", req->op.mod.message->elements[i].name); - return LDB_ERR_UNWILLING_TO_PERFORM; + if (((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE) + && el->num_values > 0) { + struct replace_context *ac2 = talloc(ac, struct replace_context); + const char **attrs = talloc_array(ac, const char *, 2); + if (!attrs || !ac2) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + attrs[0] = el->name; + attrs[1] = NULL; + + ac2->ac = ac; + ac2->el = el; + + /* We need to setup a search, compare with the list, and then setup add/del as required */ + + /* The callback does all the hard work here */ + ret = ldb_build_search_req(&new_req, module->ldb, req, + req->op.mod.message->dn, + LDB_SCOPE_BASE, + "(objectClass=*)", + attrs, + NULL, + ac2, + linked_attributes_mod_replace_search_callback); + + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(new_req, attrs); + + /* Create a spot in the list for the requests */ + 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] = talloc_steal(ac->down_req, new_req); + ac->num_requests++; + + ret = ldb_next_request(module, new_req); + + if (ret != LDB_SUCCESS) { + return ret; + } + + continue; + } else if (((el->flags & LDB_FLAG_MOD_MASK) & (LDB_FLAG_MOD_DELETE|LDB_FLAG_MOD_REPLACE)) + && el->num_values == 0) { + const char **attrs = talloc_array(ac, const char *, 2); + if (!attrs) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + attrs[0] = el->name; + attrs[1] = NULL; + + /* We need to setup a search, and then setup del as required */ + + /* The callback does all the hard work here, acting identically to if we had delted the whole entry */ + ret = ldb_build_search_req(&new_req, module->ldb, req, + req->op.mod.message->dn, + LDB_SCOPE_BASE, + "(objectClass=*)", + attrs, + NULL, + ac, + linked_attributes_rename_del_search_callback); + + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(new_req, attrs); + + /* Create a spot in the list for the requests */ + 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] = talloc_steal(ac->down_req, new_req); + ac->num_requests++; + + ret = ldb_next_request(module, new_req); + + if (ret != LDB_SUCCESS) { + return ret; + } + + continue; } /* Prepare the modify (mod element) on the targets */ /* For each value being moded, we need to setup the modify */ for (j=0; j < el->num_values; j++) { - struct ldb_request *new_req; /* Create the modify request */ - struct ldb_message *new_msg = ldb_msg_new(ac->down_req); + struct ldb_message *new_msg = ldb_msg_new(ac); if (!new_msg) { ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; @@ -406,7 +538,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques return ret; } - ret = ldb_build_mod_req(&new_req, module->ldb, ac->down_req, + ret = ldb_build_mod_req(&new_req, module->ldb, ac, new_msg, NULL, NULL, @@ -426,7 +558,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques ldb_oom(ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - ac->down_req[ac->num_requests] = new_req; + ac->down_req[ac->num_requests] = talloc_steal(ac->down_req, new_req); ac->num_requests++; /* Run the new request */ @@ -436,12 +568,11 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques } } } - return ret; + return LDB_SUCCESS; } static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) { - struct ldb_request *req; struct linked_attributes_context *ac = talloc_get_type(context, struct linked_attributes_context); struct ldb_dn *olddn, *newdn; @@ -452,6 +583,13 @@ static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, newdn = NULL; break; } + /* This isn't the general modify case, just the modify when we are asked to delete all values */ + case LDB_MODIFY: + { + olddn = ac->orig_req->op.mod.message->dn; + newdn = NULL; + break; + } case LDB_RENAME: { olddn = ac->orig_req->op.rename.olddn; @@ -478,21 +616,6 @@ static int linked_attributes_rename_del_search_callback(struct ldb_context *ldb, } else if (ares->type == LDB_REPLY_ENTRY) { /* Guh? We only asked for this DN */ return LDB_ERR_OPERATIONS_ERROR; - } else if (ares->type == LDB_REPLY_DONE) { - req = talloc(ac, struct ldb_request); - *req = *ac->orig_req; - talloc_free(ares); - - ac->down_req = talloc_realloc(ac, ac->down_req, - struct ldb_request *, ac->num_requests + 1); - if (!ac->down_req) { - ldb_oom(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); @@ -660,6 +783,27 @@ static int linked_attributes_wait_none(struct ldb_handle *handle) { return LDB_SUCCESS; } } + + /* Now run the original request */ + ac->step = LA_DO_ORIG; + return ldb_next_request(ac->module, ac->orig_down_req); + + case LA_DO_ORIG: + ret = ldb_wait(ac->orig_down_req->handle, LDB_WAIT_NONE); + + if (ret != LDB_SUCCESS) { + handle->status = ret; + goto done; + } + if (ac->orig_down_req->handle->status != LDB_SUCCESS) { + handle->status = ac->orig_down_req->handle->status; + goto done; + } + + if (ac->orig_down_req->handle->state != LDB_ASYNC_DONE) { + return LDB_SUCCESS; + } + ret = LDB_SUCCESS; } done: -- cgit From e72760b218e60acfc04c6c22a43820683172df09 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 16 Jan 2008 15:14:05 +1100 Subject: Rework linked_attributes module for the REPLACE case. This moves to a smarter 'find the delta' based operation of the linked attributes module, when the caller asks for a 'replace' of the link source. Previously we would spray operations all over the database, even if the net result was just to modify one record. This also means we need the transaction safety less, which may be useful for some LDAP backends that don't provide this functionality on the LDAP server. Andrew Bartlett (This used to be commit 8c88e4eb1c0a606e7899091525260e8d6558ffd0) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 92 ++++++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index 803d24e34e..b3fdffe566 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -279,6 +279,27 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * return setup_modifies(module->ldb, ac, ac, req->op.add.message, NULL, req->op.add.message->dn); } +struct merge { + struct ldb_dn *dn; + bool add; + bool ignore; +}; + +static int merge_cmp(struct merge *merge1, struct merge *merge2) { + int ret; + ret = ldb_dn_compare(merge1->dn, merge2->dn); + if (ret == 0) { + if (merge1->add == merge2->add) { + return 0; + } + if (merge1->add == true) { + return 1; + } + return -1; + } + return ret; +} + static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) { struct replace_context *ac2 = talloc_get_type(context, struct replace_context); @@ -296,16 +317,63 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb /* See if this element already exists */ if (search_el) { - int ret; + + struct merge *merged_list = NULL; + + int ret, size = 0, i; struct ldb_message *msg = ldb_msg_new(ac); if (!msg) { ldb_oom(ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - /* Lazy option: Delete and add the elements on all members */ - msg->num_elements = 1; - msg->elements = search_el; + /* Add all the existing elements, marking as 'proposed for delete' by setting .add = false */ + for (i=0; i < search_el->num_values; i++) { + merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1); + merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)search_el->values[i].data); + merged_list[size].add = false; + merged_list[size].ignore = false; + size++; + } + + /* Add all the new replacement elements, marking as 'proposed for add' by setting .add = true */ + for (i=0; i < ac2->el->num_values; i++) { + merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1); + merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)ac2->el->values[i].data); + merged_list[size].add = true; + merged_list[size].ignore = false; + size++; + } + + /* Sort the list, so we can pick out an add and delete for the same DN, and eliminate them */ + qsort(merged_list, size, + sizeof(*merged_list), + (comparison_fn_t)merge_cmp); + + /* Now things are sorted, it is trivial to mark pairs of DNs as 'ignore' */ + for (i=0; i + 1 < size; i++) { + if (ldb_dn_compare(merged_list[i].dn, + merged_list[i+1].dn) == 0 + /* Fortunetly the sort also sorts 'add == false' first */ + && merged_list[i].add == false + && merged_list[i+1].add == true) { + + /* Mark as ignore, so we include neither in the actual operations */ + merged_list[i].ignore = true; + merged_list[i+1].ignore = true; + } + } + + /* Arrange to delete anything the search found that we don't re-add */ + for (i=0; i < size; i++) { + if (merged_list[i].ignore == false + && merged_list[i].add == false) { + ldb_msg_add_steal_string(msg, search_el->name, + ldb_dn_get_linearized(merged_list[i].dn)); + } + } + + /* The DN to set on the linked attributes is the original DN of the modify message */ msg->dn = ac->orig_req->op.mod.message->dn; ret = setup_modifies(ac->module->ldb, ac2, ac, msg, ares->message->dn, NULL); @@ -313,13 +381,21 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb return ret; } - msg->elements = ac2->el; + /* Now add links for all the actually new elements */ + for (i=0; i < size; i++) { + if (merged_list[i].ignore == false && merged_list[i].add == true) { + ldb_msg_add_steal_string(msg, search_el->name, + ldb_dn_get_linearized(merged_list[i].dn)); + } + } ret = setup_modifies(ac->module->ldb, ac2, ac, msg, NULL, ares->message->dn); if (ret != LDB_SUCCESS) { return ret; } + talloc_free(merged_list); + } else { /* Looks like it doesn't exist, process like an 'add' */ struct ldb_message *msg = ldb_msg_new(ac); @@ -411,6 +487,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques return LDB_ERR_OBJECT_CLASS_VIOLATION; } + /* Replace with new set of values */ if (((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE) && el->num_values > 0) { struct replace_context *ac2 = talloc(ac, struct replace_context); @@ -461,6 +538,8 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques } continue; + + /* Delete all values case */ } else if (((el->flags & LDB_FLAG_MOD_MASK) & (LDB_FLAG_MOD_DELETE|LDB_FLAG_MOD_REPLACE)) && el->num_values == 0) { const char **attrs = talloc_array(ac, const char *, 2); @@ -508,7 +587,8 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques continue; } - /* Prepare the modify (mod element) on the targets */ + + /* Prepare the modify (mod element) on the targets, for a normal modify request */ /* For each value being moded, we need to setup the modify */ for (j=0; j < el->num_values; j++) { -- cgit From 16109a40c0abd8c30a5eb9bf9ef692bfae9dfc7d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 20 Feb 2008 01:54:32 +0100 Subject: Use struct-based rather than function-based initialization for ldb modules everywhere. (This used to be commit 85c96a325867f7bcdb412ebc53f8a47dbf7cd89b) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index b3fdffe566..d6e9d3da4f 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -915,7 +915,7 @@ static int linked_attributes_wait(struct ldb_handle *handle, enum ldb_wait_type } } -static const struct ldb_module_ops linked_attributes_ops = { +const struct ldb_module_ops ldb_linked_attributes_module_ops = { .name = "linked_attributes", .add = linked_attributes_add, .modify = linked_attributes_modify, @@ -923,8 +923,3 @@ static const struct ldb_module_ops linked_attributes_ops = { .rename = linked_attributes_rename, .wait = linked_attributes_wait, }; - -int ldb_linked_attributes_init(void) -{ - return ldb_register_module(&linked_attributes_ops); -} -- cgit From 39a817d310964f8e9a63cfb096b3ad24fa03bd5e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 20 Feb 2008 04:33:43 +0100 Subject: Fix use of some modules (needed _PUBLIC_). (This used to be commit ce332130ea77159832da23bab760fa26921719e2) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index d6e9d3da4f..8685c722aa 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -915,7 +915,7 @@ static int linked_attributes_wait(struct ldb_handle *handle, enum ldb_wait_type } } -const struct ldb_module_ops ldb_linked_attributes_module_ops = { +_PUBLIC_ const struct ldb_module_ops ldb_linked_attributes_module_ops = { .name = "linked_attributes", .add = linked_attributes_add, .modify = linked_attributes_modify, -- cgit From 1c1c6fca660c304630672e87c20819daf8e008fc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 29 Mar 2008 13:32:15 +1100 Subject: Fix more valgrind issues. This passes down the timeout more consistantly, and ensures that no matter how the modules screw up, we don't free() the memory we are going to write into the ASN1 packet until we actually write it out. Andrew Bartlett (This used to be commit eefd46289b90967ce6b4cd385fb1f7e1d6f9b343) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index 8685c722aa..04b9987071 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -520,6 +520,12 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques talloc_steal(new_req, attrs); + ret = ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + if (ret != LDB_SUCCESS) { + return ret; + } + /* Create a spot in the list for the requests */ ac->down_req = talloc_realloc(ac, ac->down_req, struct ldb_request *, ac->num_requests + 1); @@ -568,6 +574,12 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques talloc_steal(new_req, attrs); + ret = ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + if (ret != LDB_SUCCESS) { + return ret; + } + /* Create a spot in the list for the requests */ ac->down_req = talloc_realloc(ac, ac->down_req, struct ldb_request *, ac->num_requests + 1); @@ -629,7 +641,11 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques talloc_steal(new_req, new_msg); - ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + ret = ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + if (ret != LDB_SUCCESS) { + return ret; + } /* Now add it to the list */ ac->down_req = talloc_realloc(ac, ac->down_req, @@ -752,6 +768,12 @@ static int linked_attributes_rename(struct ldb_module *module, struct ldb_reques talloc_steal(new_req, attrs); + ret = ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + if (ret != LDB_SUCCESS) { + return ret; + } + ac->search_req = new_req; ac->step = LA_SEARCH; return ldb_next_request(module, new_req); @@ -805,6 +827,12 @@ static int linked_attributes_delete(struct ldb_module *module, struct ldb_reques talloc_steal(new_req, attrs); + ret = ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + if (ret != LDB_SUCCESS) { + return ret; + } + ac->search_req = new_req; ac->step = LA_SEARCH; return ldb_next_request(module, new_req); -- cgit From 4ad97a1d0593b3401a352407009a99ead23f21f2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Aug 2008 19:24:58 +1000 Subject: Don't walk past the end of ldb values. This is a partial fix towards bugs due to us walking past the end of what we think are strings in ldb. There is much more work to do in this area. Andrew Bartlett (This used to be commit 5805a9a8f35fd90fa4f718f73534817fa3bbdfd2) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/linked_attributes.c') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index 04b9987071..e64472432d 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -160,7 +160,7 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; } - new_msg->dn = ldb_dn_new(new_msg, ldb, (char *)el->values[j].data); + new_msg->dn = ldb_dn_from_ldb_val(new_msg, ldb, &el->values[j]); if (!new_msg->dn) { ldb_asprintf_errstring(ldb, "attribute %s value %s was not a valid DN", msg->elements[i].name, @@ -330,7 +330,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb /* Add all the existing elements, marking as 'proposed for delete' by setting .add = false */ for (i=0; i < search_el->num_values; i++) { merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1); - merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)search_el->values[i].data); + merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &search_el->values[i]); merged_list[size].add = false; merged_list[size].ignore = false; size++; @@ -339,7 +339,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb /* Add all the new replacement elements, marking as 'proposed for add' by setting .add = true */ for (i=0; i < ac2->el->num_values; i++) { merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1); - merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)ac2->el->values[i].data); + merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &ac2->el->values[i]); merged_list[size].add = true; merged_list[size].ignore = false; size++; @@ -610,7 +610,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data); + new_msg->dn = ldb_dn_from_ldb_val(new_msg, module->ldb, &el->values[j]); if (!new_msg->dn) { ldb_asprintf_errstring(module->ldb, "attribute %s value %s was not a valid DN", req->op.mod.message->elements[i].name, -- cgit