ldb database library
Copyright (C) Simo Sorce 2005
- Copyright (C) Stefa Metzmacher 2007
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
- ** 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 2 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, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ 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/>.
*/
/*
*
* Component: ldb deleted objects control module
*
- * Description: this module hides deleted objects, and returns them if the control is there
+ * Description: this module hides deleted objects, and returns them if the right 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 "ldb/include/ldb_module.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_context *ldb;
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;
+ struct ldb_parse_tree *new_tree = req->op.search.tree;
int ret;
+ ldb = ldb_module_get_ctx(module);
+
/* check if there's a show deleted control */
control = ldb_request_get_control(req, 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);
+ if (! control) {
+ /* FIXME: we could use a constant tree here once we
+ are sure that no ldb modules modify trees
+ in-situ */
+ new_tree = talloc(req, struct ldb_parse_tree);
+ if (!new_tree) {
+ ldb_oom(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_tree->operation = LDB_OP_AND;
+ new_tree->u.list.num_elements = 2;
+ new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, 2);
+ if (!new_tree->u.list.elements) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
}
- new_attrs[i] = talloc_strdup(new_attrs, "isDeleted");
- if (!new_attrs[i]) {
- ldb_oom(module->ldb);
+ new_tree->u.list.elements[0] = talloc(new_tree->u.list.elements, struct ldb_parse_tree);
+ new_tree->u.list.elements[0]->operation = LDB_OP_NOT;
+ new_tree->u.list.elements[0]->u.isnot.child =
+ talloc(new_tree->u.list.elements, struct ldb_parse_tree);
+ if (!new_tree->u.list.elements[0]->u.isnot.child) {
+ ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- new_attrs[i+1] = NULL;
- down_req->op.search.attrs = (const char * const *)new_attrs;
+ new_tree->u.list.elements[0]->u.isnot.child->operation = LDB_OP_EQUALITY;
+ new_tree->u.list.elements[0]->u.isnot.child->u.equality.attr = "isDeleted";
+ new_tree->u.list.elements[0]->u.isnot.child->u.equality.value = data_blob_string_const("TRUE");
+ new_tree->u.list.elements[1] = req->op.search.tree;
+ }
+
+ ret = ldb_build_search_req_ex(&down_req, ldb, req,
+ req->op.search.base,
+ req->op.search.scope,
+ new_tree,
+ req->op.search.attrs,
+ req->controls,
+ req->context, req->callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- 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;
+ /* mark the control as done */
+ if (control) {
+ control->critical = 0;
}
- return ret;
+ /* perform the search */
+ return ldb_next_request(module, down_req);
}
static int show_deleted_init(struct ldb_module *module)
{
- struct ldb_request *req;
+ struct ldb_context *ldb;
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;
+ ldb = ldb_module_get_ctx(module);
- ret = ldb_request(module->ldb, req);
+ ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_DELETED_OID);
if (ret != LDB_SUCCESS) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "show_deleted: Unable to register control with rootdse!\n");
- talloc_free(req);
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "show_deleted: Unable to register control with rootdse!\n");
return LDB_ERR_OPERATIONS_ERROR;
}
- talloc_free(req);
return ldb_next_init(module);
}
-static const struct ldb_module_ops show_deleted_ops = {
+_PUBLIC_ const struct ldb_module_ops ldb_show_deleted_module_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);
-}