b4f81978d3a9100c525989cefe66354494e7fe9f
[ira/wip.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         if (dsdb_flags & DSDB_MODIFY_RELAX) {
91                 ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
92                 if (ret != LDB_SUCCESS) {
93                         return ret;
94                 }
95         }
96
97         return LDB_SUCCESS;
98 }
99
100 /*
101   search for attrs on one DN, in the modules below
102  */
103 int dsdb_module_search_dn(struct ldb_module *module,
104                           TALLOC_CTX *mem_ctx,
105                           struct ldb_result **_res,
106                           struct ldb_dn *basedn,
107                           const char * const *attrs,
108                           uint32_t dsdb_flags)
109 {
110         int ret;
111         struct ldb_request *req;
112         TALLOC_CTX *tmp_ctx;
113         struct ldb_result *res;
114
115         tmp_ctx = talloc_new(mem_ctx);
116
117         res = talloc_zero(tmp_ctx, struct ldb_result);
118         if (!res) {
119                 return LDB_ERR_OPERATIONS_ERROR;
120         }
121
122         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
123                                    basedn,
124                                    LDB_SCOPE_BASE,
125                                    NULL,
126                                    attrs,
127                                    NULL,
128                                    res,
129                                    ldb_search_default_callback,
130                                    NULL);
131         if (ret != LDB_SUCCESS) {
132                 talloc_free(tmp_ctx);
133                 return ret;
134         }
135
136         ret = dsdb_request_add_controls(module, req, dsdb_flags);
137         if (ret != LDB_SUCCESS) {
138                 talloc_free(tmp_ctx);
139                 return ret;
140         }
141
142         ret = ldb_next_request(module, req);
143         if (ret == LDB_SUCCESS) {
144                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
145         }
146
147         if (ret != LDB_SUCCESS) {
148                 talloc_free(tmp_ctx);
149                 return ret;
150         }
151
152         if (res->count != 1) {
153                 /* we may be reading a DB that does not have the 'check base on search' option... */
154                 ret = LDB_ERR_NO_SUCH_OBJECT;
155                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
156                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
157                                        ldb_dn_get_linearized(basedn), res->count);
158         } else {
159                 *_res = talloc_steal(mem_ctx, res);
160         }
161         talloc_free(tmp_ctx);
162         return ret;
163 }
164
165 /*
166   search for attrs in the modules below
167  */
168 int dsdb_module_search(struct ldb_module *module,
169                        TALLOC_CTX *mem_ctx,
170                        struct ldb_result **_res,
171                        struct ldb_dn *basedn, enum ldb_scope scope, 
172                        const char * const *attrs,
173                        int dsdb_flags, 
174                        const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
175 {
176         int ret;
177         struct ldb_request *req;
178         TALLOC_CTX *tmp_ctx;
179         struct ldb_result *res;
180         va_list ap;
181         char *expression;
182
183         tmp_ctx = talloc_new(mem_ctx);
184
185         va_start(ap, format);
186         expression = talloc_vasprintf(tmp_ctx, format, ap);
187         va_end(ap);
188
189         res = talloc_zero(tmp_ctx, struct ldb_result);
190         if (!res) {
191                 return LDB_ERR_OPERATIONS_ERROR;
192         }
193
194         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
195                                    basedn,
196                                    scope,
197                                    expression,
198                                    attrs,
199                                    NULL,
200                                    res,
201                                    ldb_search_default_callback,
202                                    NULL);
203         if (ret != LDB_SUCCESS) {
204                 talloc_free(tmp_ctx);
205                 return ret;
206         }
207
208         ret = dsdb_request_add_controls(module, req, dsdb_flags);
209         if (ret != LDB_SUCCESS) {
210                 talloc_free(tmp_ctx);
211                 return ret;
212         }
213
214         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
215                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
216                 ret = ops->search(module, req);
217         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
218                 ret = ldb_request(ldb_module_get_ctx(module), req);
219         } else {
220                 ret = ldb_next_request(module, req);
221         }
222         if (ret == LDB_SUCCESS) {
223                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
224         }
225
226         talloc_free(req);
227         if (ret == LDB_SUCCESS) {
228                 *_res = talloc_steal(mem_ctx, res);
229         }
230         talloc_free(tmp_ctx);
231         return ret;
232 }
233
234 /*
235   find a DN given a GUID. This searches across all partitions
236  */
237 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
238                            const struct GUID *guid, struct ldb_dn **dn)
239 {
240         struct ldb_result *res;
241         const char *attrs[] = { NULL };
242         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
243         int ret;
244
245         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
246                                  attrs,
247                                  DSDB_SEARCH_SHOW_DELETED |
248                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
249                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
250                                  "objectGUID=%s", GUID_string(tmp_ctx, guid));
251         if (ret != LDB_SUCCESS) {
252                 talloc_free(tmp_ctx);
253                 return ret;
254         }
255         if (res->count == 0) {
256                 talloc_free(tmp_ctx);
257                 return LDB_ERR_NO_SUCH_OBJECT;
258         }
259         if (res->count != 1) {
260                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
261                                        GUID_string(tmp_ctx, guid));
262                 talloc_free(tmp_ctx);
263                 return LDB_ERR_OPERATIONS_ERROR;
264         }
265
266         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
267
268         talloc_free(tmp_ctx);
269         return LDB_SUCCESS;
270 }
271
272 /*
273   find a GUID given a DN.
274  */
275 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
276 {
277         const char *attrs[] = { NULL };
278         struct ldb_result *res;
279         TALLOC_CTX *tmp_ctx = talloc_new(module);
280         int ret;
281         NTSTATUS status;
282
283         ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
284                                     DSDB_SEARCH_SHOW_DELETED|
285                                     DSDB_SEARCH_SHOW_EXTENDED_DN);
286         if (ret != LDB_SUCCESS) {
287                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
288                                        ldb_dn_get_linearized(dn));
289                 talloc_free(tmp_ctx);
290                 return ret;
291         }
292
293         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
294         if (!NT_STATUS_IS_OK(status)) {
295                 talloc_free(tmp_ctx);
296                 return LDB_ERR_OPERATIONS_ERROR;
297         }
298
299         talloc_free(tmp_ctx);
300         return LDB_SUCCESS;
301 }
302
303 /*
304   a ldb_modify request operating on modules below the
305   current module
306  */
307 int dsdb_module_modify(struct ldb_module *module,
308                        const struct ldb_message *message,
309                        uint32_t dsdb_flags)
310 {
311         struct ldb_request *mod_req;
312         int ret;
313         struct ldb_context *ldb = ldb_module_get_ctx(module);
314         TALLOC_CTX *tmp_ctx = talloc_new(module);
315
316         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
317                                 message,
318                                 NULL,
319                                 NULL,
320                                 ldb_op_default_callback,
321                                 NULL);
322         if (ret != LDB_SUCCESS) {
323                 talloc_free(tmp_ctx);
324                 return ret;
325         }
326
327         ret = dsdb_request_add_controls(module, mod_req, dsdb_flags);
328         if (ret != LDB_SUCCESS) {
329                 talloc_free(tmp_ctx);
330                 return ret;
331         }
332
333         /* Run the new request */
334         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
335                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
336                 ret = ops->modify(module, mod_req);
337         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
338                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
339         } else {
340                 ret = ldb_next_request(module, mod_req);
341         }
342         if (ret == LDB_SUCCESS) {
343                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
344         }
345
346         talloc_free(tmp_ctx);
347         return ret;
348 }
349
350
351
352 /*
353   a ldb_rename request operating on modules below the
354   current module
355  */
356 int dsdb_module_rename(struct ldb_module *module,
357                       struct ldb_dn *olddn, struct ldb_dn *newdn,
358                       uint32_t dsdb_flags)
359 {
360         struct ldb_request *req;
361         int ret;
362         struct ldb_context *ldb = ldb_module_get_ctx(module);
363         TALLOC_CTX *tmp_ctx = talloc_new(module);
364
365         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
366                                    olddn,
367                                    newdn,
368                                    NULL,
369                                    NULL,
370                                    ldb_op_default_callback,
371                                    NULL);
372         if (ret != LDB_SUCCESS) {
373                 talloc_free(tmp_ctx);
374                 return ret;
375         }
376
377         ret = dsdb_request_add_controls(module, req, dsdb_flags);
378         if (ret != LDB_SUCCESS) {
379                 talloc_free(tmp_ctx);
380                 return ret;
381         }
382
383         /* Run the new request */
384         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
385                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
386                 ret = ops->rename(module, req);
387         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
388                 ret = ldb_request(ldb_module_get_ctx(module), req);
389         } else {
390                 ret = ldb_next_request(module, req);
391         }
392         if (ret == LDB_SUCCESS) {
393                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
394         }
395
396         talloc_free(tmp_ctx);
397         return ret;
398 }
399
400 /*
401   a ldb_add request operating on modules below the
402   current module
403  */
404 int dsdb_module_add(struct ldb_module *module,
405                     const struct ldb_message *message,
406                     uint32_t dsdb_flags)
407 {
408         struct ldb_request *req;
409         int ret;
410         struct ldb_context *ldb = ldb_module_get_ctx(module);
411         TALLOC_CTX *tmp_ctx = talloc_new(module);
412
413         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
414                                 message,
415                                 NULL,
416                                 NULL,
417                                 ldb_op_default_callback,
418                                 NULL);
419         if (ret != LDB_SUCCESS) {
420                 talloc_free(tmp_ctx);
421                 return ret;
422         }
423
424         ret = dsdb_request_add_controls(module, req, dsdb_flags);
425         if (ret != LDB_SUCCESS) {
426                 talloc_free(tmp_ctx);
427                 return ret;
428         }
429
430         /* Run the new request */
431         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
432                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
433                 ret = ops->add(module, req);
434         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
435                 ret = ldb_request(ldb_module_get_ctx(module), req);
436         } else {
437                 ret = ldb_next_request(module, req);
438         }
439         if (ret == LDB_SUCCESS) {
440                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
441         }
442
443         talloc_free(tmp_ctx);
444         return ret;
445 }
446
447
448 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
449 {
450         const struct dsdb_class *last_class = NULL;
451         int i;
452
453         for (i = 0; i < element->num_values; i++){
454                 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
455
456                 if(tmp_class == NULL) {
457                         continue;
458                 }
459
460                 if(tmp_class->objectClassCategory == 3) {
461                         continue;
462                 }
463
464                 if (!last_class) {
465                         last_class = tmp_class;
466                 } else {
467                         if (tmp_class->subClass_order > last_class->subClass_order)
468                                 last_class = tmp_class;
469                 }
470         }
471
472         return last_class;
473 }
474
475 /*
476   check if a single valued link has multiple non-deleted values
477
478   This is needed when we will be using the RELAX control to stop
479   ldb_tdb from checking single valued links
480  */
481 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
482                                   const struct ldb_message_element *el)
483 {
484         bool found_active = false;
485         int i;
486
487         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
488             el->num_values < 2) {
489                 return LDB_SUCCESS;
490         }
491
492         for (i=0; i<el->num_values; i++) {
493                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
494                         if (found_active) {
495                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
496                         }
497                         found_active = true;
498                 }
499         }
500
501         return LDB_SUCCESS;
502 }
503
504
505 /*
506   find a 'reference' DN that points at another object
507   (eg. serverReference, rIDManagerReference etc)
508  */
509 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
510                              const char *attribute, struct ldb_dn **dn)
511 {
512         const char *attrs[2];
513         struct ldb_result *res;
514         int ret;
515
516         attrs[0] = attribute;
517         attrs[1] = NULL;
518
519         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs, 0);
520         if (ret != LDB_SUCCESS) {
521                 return ret;
522         }
523
524         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
525                                       mem_ctx, res->msgs[0], attribute);
526         if (!*dn) {
527                 talloc_free(res);
528                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
529         }
530
531         talloc_free(res);
532         return LDB_SUCCESS;
533 }
534
535 /*
536   find the RID Manager$ DN via the rIDManagerReference attribute in the
537   base DN
538  */
539 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
540 {
541         return dsdb_module_reference_dn(module, mem_ctx,
542                                         samdb_base_dn(ldb_module_get_ctx(module)),
543                                         "rIDManagerReference", dn);
544 }
545
546
547 /*
548   update an integer attribute safely via a constrained delete/add
549  */
550 int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
551                                             const char *attr, uint64_t old_val, uint64_t new_val)
552 {
553         struct ldb_message *msg;
554         struct ldb_message_element *el;
555         struct ldb_val v1, v2;
556         int ret;
557         char *vstring;
558
559         msg = ldb_msg_new(module);
560         msg->dn = dn;
561
562         ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
563         if (ret != LDB_SUCCESS) {
564                 talloc_free(msg);
565                 return ret;
566         }
567         el->num_values = 1;
568         el->values = &v1;
569         vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
570         if (!vstring) {
571                 ldb_module_oom(module);
572                 talloc_free(msg);
573                 return LDB_ERR_OPERATIONS_ERROR;
574         }
575         v1 = data_blob_string_const(vstring);
576
577         ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
578         if (ret != LDB_SUCCESS) {
579                 talloc_free(msg);
580                 return ret;
581         }
582         el->num_values = 1;
583         el->values = &v2;
584         vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
585         if (!vstring) {
586                 ldb_module_oom(module);
587                 talloc_free(msg);
588                 return LDB_ERR_OPERATIONS_ERROR;
589         }
590         v2 = data_blob_string_const(vstring);
591
592         ret = dsdb_module_modify(module, msg, 0);
593         talloc_free(msg);
594         return ret;
595 }
596
597 /*
598   used to chain to the callers callback
599  */
600 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
601 {
602         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
603
604         talloc_steal(up_req, req);
605         return up_req->callback(up_req, ares);
606 }
607
608
609 /*
610   set an integer attribute
611  */
612 int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
613                             const char *attr, uint64_t new_val)
614 {
615         struct ldb_message *msg;
616         int ret;
617
618         msg = ldb_msg_new(module);
619         msg->dn = dn;
620
621         ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
622         if (ret != LDB_SUCCESS) {
623                 talloc_free(msg);
624                 return ret;
625         }
626         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
627
628         ret = dsdb_module_modify(module, msg, 0);
629         talloc_free(msg);
630         return ret;
631 }