diff options
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/config.mk | 12 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/show_deleted.c | 215 |
2 files changed, 227 insertions, 0 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 0934b4ca6a..929d0bcead 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -177,6 +177,18 @@ OBJ_FILES = \ ################################################ ################################################ +# Start MODULE ldb_show_deleted +[MODULE::ldb_show_deleted] +SUBSYSTEM = ldb +PRIVATE_DEPENDENCIES = LIBTALLOC +INIT_FUNCTION = ldb_show_deleted_init +OBJ_FILES = \ + show_deleted.o +# +# End MODULE ldb_show_deleted +################################################ + +################################################ # Start MODULE ldb_partition [MODULE::ldb_partition] SUBSYSTEM = ldb diff --git a/source4/dsdb/samdb/ldb_modules/show_deleted.c b/source4/dsdb/samdb/ldb_modules/show_deleted.c new file mode 100644 index 0000000000..9d624c9982 --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/show_deleted.c @@ -0,0 +1,215 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + Copyright (C) Stefa Metzmacher 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 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 2 of the License, or (at your option) any later version. + + This library 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb deleted objects control module + * + * Description: this module hides deleted objects, and returns them if the control is there + * + * Author: Stefan Metzmacher + */ + +#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" + +/* search */ +struct show_deleted_search_request { + + struct ldb_module *module; + void *up_context; + int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *); + + bool remove_from_msg; +}; + +static int show_deleted_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) +{ + struct show_deleted_search_request *ar; + + if (!context || !ares) { + ldb_set_errstring(ldb, "NULL Context or Result in callback"); + goto error; + } + + ar = talloc_get_type(context, struct show_deleted_search_request); + + if (ares->type == LDB_REPLY_ENTRY) { + bool isDeleted; + + isDeleted = ldb_msg_find_attr_as_bool(ares->message, "isDeleted", false); + + if (isDeleted) { + goto skip_deleted; + } + + if (ar->remove_from_msg) { + ldb_msg_remove_attr(ares->message, "isDeleted"); + } + } + + return ar->up_callback(ldb, ar->up_context, ares); + +skip_deleted: + talloc_free(ares); + return LDB_SUCCESS; +error: + talloc_free(ares); + return LDB_ERR_OPERATIONS_ERROR; +} + +static int show_deleted_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_control *control; + struct ldb_control **saved_controls; + struct show_deleted_search_request *ar; + struct ldb_request *down_req; + char **new_attrs; + uint32_t num_attrs = 0; + uint32_t i; + int ret; + + /* check if there's a show deleted control */ + control = get_control_from_list(req->controls, LDB_CONTROL_SHOW_DELETED_OID); + + /* copy the request for modification */ + down_req = talloc(req, struct ldb_request); + if (down_req == NULL) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* copy the request */ + *down_req = *req; + + /* if a control is there remove if from the modified request */ + if (control && !save_controls(control, down_req, &saved_controls)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* if we had a control, then just go on to the next request as we have nothing to hide */ + if (control) { + goto next_request; + } + + ar = talloc(down_req, struct show_deleted_search_request); + if (ar == NULL) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ar->module = module; + ar->up_context = req->context; + ar->up_callback = req->callback; + ar->remove_from_msg = true; + + /* check if attrs only is specified, in that case check wether we need to modify them */ + if (down_req->op.search.attrs) { + for (i=0; (down_req->op.search.attrs && down_req->op.search.attrs[i]); i++) { + num_attrs++; + if (strcasecmp(down_req->op.search.attrs[i], "*") == 0) { + ar->remove_from_msg = false; + } else if (strcasecmp(down_req->op.search.attrs[i], "isDeleted") == 0) { + ar->remove_from_msg = false; + } + } + } else { + ar->remove_from_msg = false; + } + + if (ar->remove_from_msg) { + new_attrs = talloc_array(down_req, char *, num_attrs + 2); + if (!new_attrs) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + for (i=0; i < num_attrs; i++) { + new_attrs[i] = discard_const_p(char, down_req->op.search.attrs[i]); + } + new_attrs[i] = talloc_strdup(new_attrs, "isDeleted"); + if (!new_attrs[i]) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + new_attrs[i+1] = NULL; + down_req->op.search.attrs = (const char * const *)new_attrs; + } + + down_req->context = ar; + down_req->callback = show_deleted_search_callback; + ldb_set_timeout_from_prev_req(module->ldb, req, down_req); + +next_request: + /* perform the search */ + ret = ldb_next_request(module, down_req); + + /* do not free down_req as the call results may be linked to it, + * it will be freed when the upper level request get freed */ + if (ret == LDB_SUCCESS) { + req->handle = down_req->handle; + } + + return ret; +} + +static int show_deleted_init(struct ldb_module *module) +{ + struct ldb_request *req; + int ret; + + req = talloc(module, struct ldb_request); + if (req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_REQ_REGISTER_CONTROL; + req->op.reg_control.oid = LDB_CONTROL_SHOW_DELETED_OID; + req->controls = NULL; + + ret = ldb_request(module->ldb, req); + if (ret != LDB_SUCCESS) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "show_deleted: Unable to register control with rootdse!\n"); + talloc_free(req); + return LDB_ERR_OPERATIONS_ERROR; + } + + talloc_free(req); + return ldb_next_init(module); +} + +static const struct ldb_module_ops show_deleted_ops = { + .name = "show_deleted", + .search = show_deleted_search, + .init_context = show_deleted_init +}; + +int ldb_show_deleted_init(void) +{ + return ldb_register_module(&show_deleted_ops); +} |