s4:dsdb/descriptor: make use of dsdb_request_sd_flags()
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / show_deleted.c
blob773dcfbf3fbd38dde97c68266de3d3dc7ae775dc
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 *attr_filter = NULL;
54 ldb = ldb_module_get_ctx(module);
56 state = talloc_get_type(ldb_module_get_private(module), struct show_deleted_state);
58 /* note that state may be NULL during initialisation */
59 if (state != NULL && state->need_refresh) {
60 state->need_refresh = false;
61 ret = dsdb_recyclebin_enabled(module, &state->recycle_bin_enabled);
62 if (ret != LDB_SUCCESS) {
63 return ret;
67 /* This is the logic from MS-ADTS 3.1.1.3.4.1.14 that
68 determines if objects are visible
70 Extended control name Deleted-objects Tombstones Recycled-objects
71 LDAP_SERVER_SHOW_DELETED_OID Visible Visible Not Visible
72 LDAP_SERVER_SHOW_RECYCLED_OID Visible Visible Visible
74 Note that if the recycle bin is disabled, then the
75 isRecycled attribute is ignored, and objects are either
76 "normal" or "tombstone".
78 When the recycle bin is enabled, then objects are in one of
79 3 states, "normal", "deleted" or "recycled"
82 /* check if there's a show deleted control */
83 show_del = ldb_request_get_control(req, LDB_CONTROL_SHOW_DELETED_OID);
84 /* check if there's a show recycled control */
85 show_rec = ldb_request_get_control(req, LDB_CONTROL_SHOW_RECYCLED_OID);
88 if (state == NULL || !state->recycle_bin_enabled) {
89 /* when recycle bin is not enabled, then all we look
90 at is the isDeleted attribute. We hide objects with this
91 attribute set to TRUE when the client has not specified either
92 SHOW_DELETED or SHOW_RECYCLED
94 if (show_del != NULL || show_rec != NULL) {
95 attr_filter = NULL;
96 } else {
97 attr_filter = "isDeleted";
99 } else {
100 /* the recycle bin is enabled
102 if (show_rec != NULL) {
103 attr_filter = NULL;
104 } else if (show_del != NULL) {
105 /* we want deleted but not recycled objects */
106 attr_filter = "isRecycled";
107 } else {
108 /* we don't want deleted or recycled objects,
109 * which we get by filtering on isDeleted */
110 attr_filter = "isDeleted";
115 if (attr_filter != NULL) {
116 new_tree = talloc(req, struct ldb_parse_tree);
117 if (!new_tree) {
118 return ldb_oom(ldb);
120 new_tree->operation = LDB_OP_AND;
121 new_tree->u.list.num_elements = 2;
122 new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, 2);
123 if (!new_tree->u.list.elements) {
124 return ldb_oom(ldb);
127 new_tree->u.list.elements[0] = talloc(new_tree->u.list.elements, struct ldb_parse_tree);
128 new_tree->u.list.elements[0]->operation = LDB_OP_NOT;
129 new_tree->u.list.elements[0]->u.isnot.child =
130 talloc(new_tree->u.list.elements, struct ldb_parse_tree);
131 if (!new_tree->u.list.elements[0]->u.isnot.child) {
132 return ldb_oom(ldb);
134 new_tree->u.list.elements[0]->u.isnot.child->operation = LDB_OP_EQUALITY;
135 new_tree->u.list.elements[0]->u.isnot.child->u.equality.attr = attr_filter;
136 new_tree->u.list.elements[0]->u.isnot.child->u.equality.value = data_blob_string_const("TRUE");
137 new_tree->u.list.elements[1] = req->op.search.tree;
140 ret = ldb_build_search_req_ex(&down_req, ldb, req,
141 req->op.search.base,
142 req->op.search.scope,
143 new_tree,
144 req->op.search.attrs,
145 req->controls,
146 req, dsdb_next_callback,
147 req);
148 LDB_REQ_SET_LOCATION(down_req);
149 if (ret != LDB_SUCCESS) {
150 return ret;
153 /* mark the controls as done */
154 if (show_del != NULL) {
155 show_del->critical = 0;
157 if (show_rec != NULL) {
158 show_rec->critical = 0;
161 /* perform the search */
162 return ldb_next_request(module, down_req);
165 static int show_deleted_init(struct ldb_module *module)
167 struct ldb_context *ldb;
168 int ret;
169 struct show_deleted_state *state;
171 state = talloc_zero(module, struct show_deleted_state);
172 if (state == NULL) {
173 return ldb_module_oom(module);
175 state->need_refresh = true;
177 ldb = ldb_module_get_ctx(module);
179 ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_DELETED_OID);
180 if (ret != LDB_SUCCESS) {
181 ldb_debug(ldb, LDB_DEBUG_ERROR,
182 "show_deleted: Unable to register control with rootdse!\n");
183 return ldb_operr(ldb);
186 ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_RECYCLED_OID);
187 if (ret != LDB_SUCCESS) {
188 ldb_debug(ldb, LDB_DEBUG_ERROR,
189 "show_deleted: Unable to register control with rootdse!\n");
190 return ldb_operr(ldb);
193 ret = ldb_next_init(module);
195 ldb_module_set_private(module, state);
197 return ret;
200 static const struct ldb_module_ops ldb_show_deleted_module_ops = {
201 .name = "show_deleted",
202 .search = show_deleted_search,
203 .init_context = show_deleted_init
206 int ldb_show_deleted_module_init(const char *version)
208 LDB_MODULE_CHECK_VERSION(version);
209 return ldb_register_module(&ldb_show_deleted_module_ops);