s4-dsdb: use varargs expression in dsdb_module_search()
[samba.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 "librpc/ndr/libndr.h"
26 #include "dsdb/samdb/ldb_modules/util.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "util.h"
29
30 /*
31   add a set of controls to a ldb_request structure based on a set of
32   flags. See util.h for a list of available flags
33  */
34 int dsdb_request_add_controls(struct ldb_module *module, struct ldb_request *req, uint32_t dsdb_flags)
35 {
36         int ret;
37         if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
38                 struct ldb_search_options_control *options;
39                 /* Using the phantom root control allows us to search all partitions */
40                 options = talloc(req, struct ldb_search_options_control);
41                 if (options == NULL) {
42                         ldb_module_oom(module);
43                         return LDB_ERR_OPERATIONS_ERROR;
44                 }
45                 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
46                 
47                 ret = ldb_request_add_control(req,
48                                               LDB_CONTROL_SEARCH_OPTIONS_OID,
49                                               true, options);
50                 if (ret != LDB_SUCCESS) {
51                         return ret;
52                 }
53         }
54
55         if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
56                 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
57                 if (ret != LDB_SUCCESS) {
58                         return ret;
59                 }
60         }
61
62         if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
63                 ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
64                 if (ret != LDB_SUCCESS) {
65                         return ret;
66                 }
67         }
68
69         if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
70                 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
71                 if (!extended_ctrl) {
72                         ldb_module_oom(module);
73                         return LDB_ERR_OPERATIONS_ERROR;
74                 }
75                 extended_ctrl->type = 1;
76                 
77                 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
78                 if (ret != LDB_SUCCESS) {
79                         return ret;
80                 }
81         }
82
83         if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
84                 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
85                 if (ret != LDB_SUCCESS) {
86                         return ret;
87                 }
88         }
89
90         return LDB_SUCCESS;
91 }
92
93 /*
94   search for attrs on one DN, in the modules below
95  */
96 int dsdb_module_search_dn(struct ldb_module *module,
97                           TALLOC_CTX *mem_ctx,
98                           struct ldb_result **_res,
99                           struct ldb_dn *basedn,
100                           const char * const *attrs,
101                           uint32_t dsdb_flags)
102 {
103         int ret;
104         struct ldb_request *req;
105         TALLOC_CTX *tmp_ctx;
106         struct ldb_result *res;
107
108         tmp_ctx = talloc_new(mem_ctx);
109
110         res = talloc_zero(tmp_ctx, struct ldb_result);
111         if (!res) {
112                 return LDB_ERR_OPERATIONS_ERROR;
113         }
114
115         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
116                                    basedn,
117                                    LDB_SCOPE_BASE,
118                                    NULL,
119                                    attrs,
120                                    NULL,
121                                    res,
122                                    ldb_search_default_callback,
123                                    NULL);
124         if (ret != LDB_SUCCESS) {
125                 talloc_free(tmp_ctx);
126                 return ret;
127         }
128
129         ret = dsdb_request_add_controls(module, req, dsdb_flags);
130         if (ret != LDB_SUCCESS) {
131                 talloc_free(tmp_ctx);
132                 return ret;
133         }
134
135         ret = ldb_next_request(module, req);
136         if (ret == LDB_SUCCESS) {
137                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
138         }
139
140         if (ret != LDB_SUCCESS) {
141                 talloc_free(tmp_ctx);
142                 return ret;
143         }
144
145         if (res->count != 1) {
146                 /* we may be reading a DB that does not have the 'check base on search' option... */
147                 ret = LDB_ERR_NO_SUCH_OBJECT;
148                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
149                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
150                                        ldb_dn_get_linearized(basedn), res->count);
151         } else {
152                 *_res = talloc_steal(mem_ctx, res);
153         }
154         talloc_free(tmp_ctx);
155         return ret;
156 }
157
158 /*
159   search for attrs in the modules below
160  */
161 int dsdb_module_search(struct ldb_module *module,
162                        TALLOC_CTX *mem_ctx,
163                        struct ldb_result **_res,
164                        struct ldb_dn *basedn, enum ldb_scope scope, 
165                        const char * const *attrs,
166                        int dsdb_flags, 
167                        const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
168 {
169         int ret;
170         struct ldb_request *req;
171         TALLOC_CTX *tmp_ctx;
172         struct ldb_result *res;
173         va_list ap;
174         char *expression;
175
176         tmp_ctx = talloc_new(mem_ctx);
177
178         va_start(ap, format);
179         expression = talloc_vasprintf(tmp_ctx, format, ap);
180         va_end(ap);
181
182         res = talloc_zero(tmp_ctx, struct ldb_result);
183         if (!res) {
184                 return LDB_ERR_OPERATIONS_ERROR;
185         }
186
187         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
188                                    basedn,
189                                    scope,
190                                    expression,
191                                    attrs,
192                                    NULL,
193                                    res,
194                                    ldb_search_default_callback,
195                                    NULL);
196         if (ret != LDB_SUCCESS) {
197                 talloc_free(tmp_ctx);
198                 return ret;
199         }
200
201         ret = dsdb_request_add_controls(module, req, dsdb_flags);
202         if (ret != LDB_SUCCESS) {
203                 talloc_free(tmp_ctx);
204                 return ret;
205         }
206
207         ret = ldb_next_request(module, req);
208         if (ret == LDB_SUCCESS) {
209                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
210         }
211
212         talloc_free(req);
213         if (ret == LDB_SUCCESS) {
214                 *_res = talloc_steal(mem_ctx, res);
215         }
216         talloc_free(tmp_ctx);
217         return ret;
218 }
219
220 /*
221   find a DN given a GUID. This searches across all partitions
222  */
223 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
224                            const struct GUID *guid, struct ldb_dn **dn)
225 {
226         struct ldb_result *res;
227         const char *attrs[] = { NULL };
228         char *expression;
229         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
230         int ret;
231
232         expression = talloc_asprintf(tmp_ctx, "objectGUID=%s", GUID_string(tmp_ctx, guid));
233         if (!expression) {
234                 ldb_module_oom(module);
235                 return LDB_ERR_OPERATIONS_ERROR;
236         }
237
238         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
239                                  attrs,
240                                  DSDB_SEARCH_SHOW_DELETED |
241                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
242                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
243                                  expression);
244         if (ret != LDB_SUCCESS) {
245                 talloc_free(tmp_ctx);
246                 return ret;
247         }
248         if (res->count == 0) {
249                 talloc_free(tmp_ctx);
250                 return LDB_ERR_NO_SUCH_OBJECT;
251         }
252         if (res->count != 1) {
253                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching %s\n",
254                                        expression);
255                 talloc_free(tmp_ctx);
256                 return LDB_ERR_OPERATIONS_ERROR;
257         }
258
259         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
260
261         talloc_free(tmp_ctx);
262         return LDB_SUCCESS;
263 }
264
265 /*
266   a ldb_modify request operating on modules below the
267   current module
268  */
269 int dsdb_module_modify(struct ldb_module *module,
270                        const struct ldb_message *message,
271                        uint32_t dsdb_flags)
272 {
273         struct ldb_request *mod_req;
274         int ret;
275         struct ldb_context *ldb = ldb_module_get_ctx(module);
276         TALLOC_CTX *tmp_ctx = talloc_new(module);
277
278         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
279                                 message,
280                                 NULL,
281                                 NULL,
282                                 ldb_op_default_callback,
283                                 NULL);
284         if (ret != LDB_SUCCESS) {
285                 talloc_free(tmp_ctx);
286                 return ret;
287         }
288
289         ret = dsdb_request_add_controls(module, mod_req, dsdb_flags);
290         if (ret != LDB_SUCCESS) {
291                 talloc_free(tmp_ctx);
292                 return ret;
293         }
294
295         /* Run the new request */
296         ret = ldb_next_request(module, mod_req);
297         if (ret == LDB_SUCCESS) {
298                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
299         }
300
301         talloc_free(tmp_ctx);
302         return ret;
303 }
304
305
306
307 /*
308   a ldb_rename request operating on modules below the
309   current module
310  */
311 int dsdb_module_rename(struct ldb_module *module,
312                       struct ldb_dn *olddn, struct ldb_dn *newdn,
313                       uint32_t dsdb_flags)
314 {
315         struct ldb_request *req;
316         int ret;
317         struct ldb_context *ldb = ldb_module_get_ctx(module);
318         TALLOC_CTX *tmp_ctx = talloc_new(module);
319
320         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
321                                    olddn,
322                                    newdn,
323                                    NULL,
324                                    NULL,
325                                    ldb_op_default_callback,
326                                    NULL);
327         if (ret != LDB_SUCCESS) {
328                 talloc_free(tmp_ctx);
329                 return ret;
330         }
331
332         ret = dsdb_request_add_controls(module, req, dsdb_flags);
333         if (ret != LDB_SUCCESS) {
334                 talloc_free(tmp_ctx);
335                 return ret;
336         }
337
338         /* Run the new request */
339         ret = ldb_next_request(module, req);
340         if (ret == LDB_SUCCESS) {
341                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
342         }
343
344         talloc_free(tmp_ctx);
345         return ret;
346 }
347
348 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
349 {
350         const struct dsdb_class *last_class = NULL;
351         int i;
352
353         for (i = 0; i < element->num_values; i++){
354                 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
355
356                 if(tmp_class == NULL) {
357                         continue;
358                 }
359
360                 if(tmp_class->objectClassCategory == 3) {
361                         continue;
362                 }
363
364                 if (!last_class) {
365                         last_class = tmp_class;
366                 } else {
367                         if (tmp_class->subClass_order > last_class->subClass_order)
368                                 last_class = tmp_class;
369                 }
370         }
371
372         return last_class;
373 }