s3:smbd: consistently use talloc_tos() memory for rpc_pipe_open_interface()
[Samba.git] / source4 / dsdb / samdb / ldb_modules / show_deleted.c
blobe3dcad5e72bc222af9c5a382e022fa6c45e13c73
1 /*
2 ldb database library
4 Copyright (C) Simo Sorce 2005
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7 Copyright (C) Matthias Dieter Wallnöfer 2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * Name: ldb
26 * Component: ldb deleted objects control module
28 * Description: this module hides deleted and recylced objects, and returns
29 * them if the right control is there
31 * Author: Stefan Metzmacher
34 #include "includes.h"
35 #include <ldb_module.h>
36 #include "dsdb/samdb/samdb.h"
37 #include "dsdb/samdb/ldb_modules/util.h"
39 struct show_deleted_state {
40 bool need_refresh;
41 bool recycle_bin_enabled;
44 static int show_deleted_search(struct ldb_module *module, struct ldb_request *req)
46 struct ldb_context *ldb;
47 struct ldb_control *show_del, *show_rec;
48 struct ldb_request *down_req;
49 struct ldb_parse_tree *new_tree = req->op.search.tree;
50 struct show_deleted_state *state;
51 int ret;
52 const char *exclude_filter = NULL;
54 /* do not manipulate our control entries */
55 if (ldb_dn_is_special(req->op.search.base)) {
56 return ldb_next_request(module, req);
59 ldb = ldb_module_get_ctx(module);
61 /* This is the logic from MS-ADTS 3.1.1.3.4.1.14 that
62 determines if objects are visible
64 Extended control name Deleted-objects Tombstones Recycled-objects
65 LDAP_SERVER_SHOW_DELETED_OID Visible Visible Not Visible
66 LDAP_SERVER_SHOW_RECYCLED_OID Visible Visible Visible
68 Note that if the recycle bin is disabled, then the
69 isRecycled attribute is ignored, and objects are either
70 "normal" or "tombstone".
72 When the recycle bin is enabled, then objects are in one of
73 3 states, "normal", "deleted" or "recycled"
76 /* check if there's a show deleted control */
77 show_del = ldb_request_get_control(req, LDB_CONTROL_SHOW_DELETED_OID);
78 /* check if there's a show recycled control */
79 show_rec = ldb_request_get_control(req, LDB_CONTROL_SHOW_RECYCLED_OID);
82 * When recycle bin is not enabled, then all we look
83 * at is the isDeleted attribute. We hide objects with this
84 * attribute set to TRUE when the client has not specified either
85 * SHOW_DELETED or SHOW_RECYCLED
87 if (show_rec == NULL && show_del == NULL) {
88 /* We don't want deleted or recycled objects,
89 * which we get by filtering on isDeleted */
90 exclude_filter = "isDeleted";
91 } else {
92 state = talloc_get_type(ldb_module_get_private(module), struct show_deleted_state);
94 /* Note that state may be NULL during initialisation */
95 if (state != NULL && state->need_refresh) {
96 /* Do not move this assignment, it can cause recursion loops! */
97 state->need_refresh = false;
98 ret = dsdb_recyclebin_enabled(module, &state->recycle_bin_enabled);
99 if (ret != LDB_SUCCESS) {
100 state->recycle_bin_enabled = false;
102 * We can fail to find the feature object
103 * during provision. Ignore any such error and
104 * assume the recycle bin cannot be enabled at
105 * this point in time.
107 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
108 state->need_refresh = true;
109 return LDB_ERR_UNWILLING_TO_PERFORM;
114 if (state != NULL && state->recycle_bin_enabled) {
116 * The recycle bin is enabled, so we want deleted not
117 * recycled.
119 if (show_rec == NULL) {
120 exclude_filter = "isRecycled";
125 if (exclude_filter != NULL) {
126 new_tree = talloc(req, struct ldb_parse_tree);
127 if (!new_tree) {
128 return ldb_oom(ldb);
130 new_tree->operation = LDB_OP_AND;
131 new_tree->u.list.num_elements = 2;
132 new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, 2);
133 if (!new_tree->u.list.elements) {
134 return ldb_oom(ldb);
137 new_tree->u.list.elements[0] = talloc(new_tree->u.list.elements, struct ldb_parse_tree);
138 new_tree->u.list.elements[0]->operation = LDB_OP_NOT;
139 new_tree->u.list.elements[0]->u.isnot.child =
140 talloc(new_tree->u.list.elements, struct ldb_parse_tree);
141 if (!new_tree->u.list.elements[0]->u.isnot.child) {
142 return ldb_oom(ldb);
144 new_tree->u.list.elements[0]->u.isnot.child->operation = LDB_OP_EQUALITY;
145 new_tree->u.list.elements[0]->u.isnot.child->u.equality.attr = exclude_filter;
146 new_tree->u.list.elements[0]->u.isnot.child->u.equality.value = data_blob_string_const("TRUE");
147 new_tree->u.list.elements[1] = req->op.search.tree;
150 ret = ldb_build_search_req_ex(&down_req, ldb, req,
151 req->op.search.base,
152 req->op.search.scope,
153 new_tree,
154 req->op.search.attrs,
155 req->controls,
156 req, dsdb_next_callback,
157 req);
158 LDB_REQ_SET_LOCATION(down_req);
159 if (ret != LDB_SUCCESS) {
160 return ret;
163 /* mark the controls as done */
164 if (show_del != NULL) {
165 show_del->critical = 0;
167 if (show_rec != NULL) {
168 show_rec->critical = 0;
171 /* perform the search */
172 return ldb_next_request(module, down_req);
175 static int show_deleted_init(struct ldb_module *module)
177 struct ldb_context *ldb;
178 int ret;
179 struct show_deleted_state *state;
181 state = talloc_zero(module, struct show_deleted_state);
182 if (state == NULL) {
183 return ldb_module_oom(module);
185 state->need_refresh = true;
187 ldb = ldb_module_get_ctx(module);
189 ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_DELETED_OID);
190 if (ret != LDB_SUCCESS) {
191 ldb_debug(ldb, LDB_DEBUG_ERROR,
192 "show_deleted: Unable to register control with rootdse!\n");
193 return ldb_operr(ldb);
196 ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_RECYCLED_OID);
197 if (ret != LDB_SUCCESS) {
198 ldb_debug(ldb, LDB_DEBUG_ERROR,
199 "show_deleted: Unable to register control with rootdse!\n");
200 return ldb_operr(ldb);
203 ret = ldb_next_init(module);
205 ldb_module_set_private(module, state);
207 return ret;
210 static const struct ldb_module_ops ldb_show_deleted_module_ops = {
211 .name = "show_deleted",
212 .search = show_deleted_search,
213 .init_context = show_deleted_init
216 int ldb_show_deleted_module_init(const char *version)
218 LDB_MODULE_CHECK_VERSION(version);
219 return ldb_register_module(&ldb_show_deleted_module_ops);