s4-dsdb: rename dsdb_module_search_handle_flags to dsdb_request_add_controls
[kai/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Andrew Tridgell 2009
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "ldb.h"
24 #include "ldb_module.h"
25 #include "dsdb/samdb/ldb_modules/util.h"
26 #include "dsdb/samdb/samdb.h"
27
28 /*
29   add a set of controls to a ldb_request structure based on a set of
30   flags. See util.h for a list of available flags
31  */
32 int dsdb_request_add_controls(struct ldb_module *module, struct ldb_request *req, uint32_t dsdb_flags)
33 {
34         int ret;
35         if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
36                 struct ldb_search_options_control *options;
37                 /* Using the phantom root control allows us to search all partitions */
38                 options = talloc(req, struct ldb_search_options_control);
39                 if (options == NULL) {
40                         ldb_module_oom(module);
41                         return LDB_ERR_OPERATIONS_ERROR;
42                 }
43                 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
44                 
45                 ret = ldb_request_add_control(req,
46                                               LDB_CONTROL_SEARCH_OPTIONS_OID,
47                                               true, options);
48                 if (ret != LDB_SUCCESS) {
49                         return ret;
50                 }
51         }
52
53         if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
54                 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
55                 if (ret != LDB_SUCCESS) {
56                         return ret;
57                 }
58         }
59
60         if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
61                 ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
62                 if (ret != LDB_SUCCESS) {
63                         return ret;
64                 }
65         }
66
67         if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
68                 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
69                 if (!extended_ctrl) {
70                         ldb_module_oom(module);
71                         return LDB_ERR_OPERATIONS_ERROR;
72                 }
73                 extended_ctrl->type = 1;
74                 
75                 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
76                 if (ret != LDB_SUCCESS) {
77                         return ret;
78                 }
79         }
80
81         if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
82                 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
83                 if (ret != LDB_SUCCESS) {
84                         return ret;
85                 }
86         }
87
88         return LDB_SUCCESS;
89 }
90
91 /*
92   search for attrs on one DN, in the modules below
93  */
94 int dsdb_module_search_dn(struct ldb_module *module,
95                           TALLOC_CTX *mem_ctx,
96                           struct ldb_result **_res,
97                           struct ldb_dn *basedn,
98                           const char * const *attrs,
99                           int dsdb_flags)
100 {
101         int ret;
102         struct ldb_request *req;
103         TALLOC_CTX *tmp_ctx;
104         struct ldb_result *res;
105
106         tmp_ctx = talloc_new(mem_ctx);
107
108         res = talloc_zero(tmp_ctx, struct ldb_result);
109         if (!res) {
110                 return LDB_ERR_OPERATIONS_ERROR;
111         }
112
113         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
114                                    basedn,
115                                    LDB_SCOPE_BASE,
116                                    NULL,
117                                    attrs,
118                                    NULL,
119                                    res,
120                                    ldb_search_default_callback,
121                                    NULL);
122         if (ret != LDB_SUCCESS) {
123                 talloc_free(tmp_ctx);
124                 return ret;
125         }
126
127         ret = dsdb_request_add_controls(module, req, dsdb_flags);
128         if (ret != LDB_SUCCESS) {
129                 talloc_free(tmp_ctx);
130                 return ret;
131         }
132
133         ret = ldb_next_request(module, req);
134         if (ret == LDB_SUCCESS) {
135                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
136         }
137
138         if (ret != LDB_SUCCESS) {
139                 talloc_free(tmp_ctx);
140                 return ret;
141         }
142
143         if (res->count != 1) {
144                 /* we may be reading a DB that does not have the 'check base on search' option... */
145                 ret = LDB_ERR_NO_SUCH_OBJECT;
146                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
147                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
148                                        ldb_dn_get_linearized(basedn), res->count);
149         } else {
150                 *_res = talloc_steal(mem_ctx, res);
151         }
152         talloc_free(tmp_ctx);
153         return ret;
154 }
155
156 /*
157   search for attrs in the modules below
158  */
159 int dsdb_module_search(struct ldb_module *module,
160                        TALLOC_CTX *mem_ctx,
161                        struct ldb_result **_res,
162                        struct ldb_dn *basedn, enum ldb_scope scope, 
163                        const char * const *attrs,
164                        int dsdb_flags, 
165                        const char *expression)
166 {
167         int ret;
168         struct ldb_request *req;
169         TALLOC_CTX *tmp_ctx;
170         struct ldb_result *res;
171
172         tmp_ctx = talloc_new(mem_ctx);
173
174         res = talloc_zero(tmp_ctx, struct ldb_result);
175         if (!res) {
176                 return LDB_ERR_OPERATIONS_ERROR;
177         }
178
179         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
180                                    basedn,
181                                    scope,
182                                    expression,
183                                    attrs,
184                                    NULL,
185                                    res,
186                                    ldb_search_default_callback,
187                                    NULL);
188         if (ret != LDB_SUCCESS) {
189                 talloc_free(tmp_ctx);
190                 return ret;
191         }
192
193         ret = dsdb_request_add_controls(module, req, dsdb_flags);
194         if (ret != LDB_SUCCESS) {
195                 talloc_free(tmp_ctx);
196                 return ret;
197         }
198
199         ret = ldb_next_request(module, req);
200         if (ret == LDB_SUCCESS) {
201                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
202         }
203
204         talloc_free(req);
205         if (ret == LDB_SUCCESS) {
206                 *_res = talloc_steal(mem_ctx, res);
207         }
208         talloc_free(tmp_ctx);
209         return ret;
210 }
211
212 /*
213   find a DN given a GUID. This searches across all partitions
214  */
215 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
216                            const struct GUID *guid, struct ldb_dn **dn)
217 {
218         struct ldb_result *res;
219         const char *attrs[] = { NULL };
220         char *expression;
221         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
222         int ret;
223
224         expression = talloc_asprintf(tmp_ctx, "objectGUID=%s", GUID_string(tmp_ctx, guid));
225         if (!expression) {
226                 ldb_module_oom(module);
227                 return LDB_ERR_OPERATIONS_ERROR;
228         }
229
230         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
231                                  attrs, DSDB_SEARCH_SHOW_DELETED | DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
232                                  expression);
233         if (ret != LDB_SUCCESS) {
234                 talloc_free(tmp_ctx);
235                 return ret;
236         }
237         if (ret->count == 0) {
238                 talloc_free(tmp_ctx);
239                 return LDB_ERR_NO_SUCH_OBJECT;
240         }
241         if (res->count != 1) {
242                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching %s\n",
243                                        expression);
244                 talloc_free(tmp_ctx);
245                 return LDB_ERR_OPERATIONS_ERROR;
246         }
247
248         *dn = talloc_steal(mem_ctx, res->msgs[0].dn);
249
250         talloc_free(tmp_ctx);
251         return LDB_SUCCESS;
252 }