s4-dsdb: introduce dsdb_module_search_tree
[kai/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 #include "libcli/security/security.h"
30
31 /*
32   search for attrs on one DN, in the modules below
33  */
34 int dsdb_module_search_dn(struct ldb_module *module,
35                           TALLOC_CTX *mem_ctx,
36                           struct ldb_result **_res,
37                           struct ldb_dn *basedn,
38                           const char * const *attrs,
39                           uint32_t dsdb_flags,
40                           struct ldb_request *parent)
41 {
42         int ret;
43         struct ldb_request *req;
44         TALLOC_CTX *tmp_ctx;
45         struct ldb_result *res;
46
47         tmp_ctx = talloc_new(mem_ctx);
48
49         res = talloc_zero(tmp_ctx, struct ldb_result);
50         if (!res) {
51                 talloc_free(tmp_ctx);
52                 return ldb_oom(ldb_module_get_ctx(module));
53         }
54
55         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
56                                    basedn,
57                                    LDB_SCOPE_BASE,
58                                    NULL,
59                                    attrs,
60                                    NULL,
61                                    res,
62                                    ldb_search_default_callback,
63                                    parent);
64         LDB_REQ_SET_LOCATION(req);
65         if (ret != LDB_SUCCESS) {
66                 talloc_free(tmp_ctx);
67                 return ret;
68         }
69
70         ret = dsdb_request_add_controls(req, dsdb_flags);
71         if (ret != LDB_SUCCESS) {
72                 talloc_free(tmp_ctx);
73                 return ret;
74         }
75
76         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
77                 ldb_req_mark_trusted(req);
78         }
79
80         /* Run the new request */
81         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
82                 ret = ldb_next_request(module, req);
83         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
84                 ret = ldb_request(ldb_module_get_ctx(module), req);
85         } else {
86                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
87                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
88                 ret = ops->search(module, req);
89         }
90         if (ret == LDB_SUCCESS) {
91                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
92         }
93
94         if (ret != LDB_SUCCESS) {
95                 talloc_free(tmp_ctx);
96                 return ret;
97         }
98
99         if (res->count != 1) {
100                 /* we may be reading a DB that does not have the 'check base on search' option... */
101                 ret = LDB_ERR_NO_SUCH_OBJECT;
102                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
103                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
104                                        ldb_dn_get_linearized(basedn), res->count);
105         } else {
106                 *_res = talloc_steal(mem_ctx, res);
107         }
108         talloc_free(tmp_ctx);
109         return ret;
110 }
111
112 int dsdb_module_search_tree(struct ldb_module *module,
113                        TALLOC_CTX *mem_ctx,
114                        struct ldb_result **_res,
115                        struct ldb_dn *basedn,
116                        enum ldb_scope scope,
117                        struct ldb_parse_tree *tree,
118                        const char * const *attrs,
119                        int dsdb_flags,
120                        struct ldb_request *parent)
121 {
122         int ret;
123         struct ldb_request *req;
124         TALLOC_CTX *tmp_ctx;
125         struct ldb_result *res;
126
127         tmp_ctx = talloc_new(mem_ctx);
128
129
130         res = talloc_zero(tmp_ctx, struct ldb_result);
131         if (!res) {
132                 talloc_free(tmp_ctx);
133                 return ldb_oom(ldb_module_get_ctx(module));
134         }
135
136         ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
137                                    basedn,
138                                    scope,
139                                    tree,
140                                    attrs,
141                                    NULL,
142                                    res,
143                                    ldb_search_default_callback,
144                                    parent);
145         LDB_REQ_SET_LOCATION(req);
146         if (ret != LDB_SUCCESS) {
147                 talloc_free(tmp_ctx);
148                 return ret;
149         }
150
151         ret = dsdb_request_add_controls(req, dsdb_flags);
152         if (ret != LDB_SUCCESS) {
153                 talloc_free(tmp_ctx);
154                 return ret;
155         }
156
157         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
158                 ldb_req_mark_trusted(req);
159         }
160
161         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
162                 ret = ldb_next_request(module, req);
163         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
164                 ret = ldb_request(ldb_module_get_ctx(module), req);
165         } else {
166                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
167                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
168                 ret = ops->search(module, req);
169         }
170         if (ret == LDB_SUCCESS) {
171                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
172         }
173
174         talloc_free(req);
175         if (ret == LDB_SUCCESS) {
176                 *_res = talloc_steal(mem_ctx, res);
177         }
178         talloc_free(tmp_ctx);
179         return ret;
180 }
181
182 /*
183   search for attrs in the modules below
184  */
185 int dsdb_module_search(struct ldb_module *module,
186                        TALLOC_CTX *mem_ctx,
187                        struct ldb_result **_res,
188                        struct ldb_dn *basedn, enum ldb_scope scope,
189                        const char * const *attrs,
190                        int dsdb_flags,
191                        struct ldb_request *parent,
192                        const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
193 {
194         int ret;
195         TALLOC_CTX *tmp_ctx;
196         va_list ap;
197         char *expression;
198         struct ldb_parse_tree *tree;
199
200         tmp_ctx = talloc_new(mem_ctx);
201
202         if (format) {
203                 va_start(ap, format);
204                 expression = talloc_vasprintf(tmp_ctx, format, ap);
205                 va_end(ap);
206
207                 if (!expression) {
208                         talloc_free(tmp_ctx);
209                         return ldb_oom(ldb_module_get_ctx(module));
210                 }
211         } else {
212                 expression = NULL;
213         }
214
215         tree = ldb_parse_tree(tmp_ctx, expression);
216         if (tree == NULL) {
217                 talloc_free(tmp_ctx);
218                 ldb_set_errstring(ldb_module_get_ctx(module),
219                                 "Unable to parse search expression");
220                 return LDB_ERR_OPERATIONS_ERROR;
221         }
222
223         ret = dsdb_module_search_tree(module,
224                        mem_ctx,
225                        _res,
226                        basedn,
227                        scope,
228                        tree,
229                        attrs,
230                        dsdb_flags,
231                        parent);
232
233         talloc_free(tmp_ctx);
234         return ret;
235 }
236
237 /*
238   find a DN given a GUID. This searches across all partitions
239  */
240 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
241                            const struct GUID *guid, struct ldb_dn **dn,
242                            struct ldb_request *parent)
243 {
244         struct ldb_result *res;
245         const char *attrs[] = { NULL };
246         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
247         int ret;
248
249         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
250                                  attrs,
251                                  DSDB_FLAG_NEXT_MODULE |
252                                  DSDB_SEARCH_SHOW_RECYCLED |
253                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
254                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
255                                  parent,
256                                  "objectGUID=%s", GUID_string(tmp_ctx, guid));
257         if (ret != LDB_SUCCESS) {
258                 talloc_free(tmp_ctx);
259                 return ret;
260         }
261         if (res->count == 0) {
262                 talloc_free(tmp_ctx);
263                 return LDB_ERR_NO_SUCH_OBJECT;
264         }
265         if (res->count != 1) {
266                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
267                                        GUID_string(tmp_ctx, guid));
268                 talloc_free(tmp_ctx);
269                 return LDB_ERR_OPERATIONS_ERROR;
270         }
271
272         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
273
274         talloc_free(tmp_ctx);
275         return LDB_SUCCESS;
276 }
277
278 /*
279   find a GUID given a DN.
280  */
281 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
282                            struct ldb_request *parent)
283 {
284         const char *attrs[] = { NULL };
285         struct ldb_result *res;
286         TALLOC_CTX *tmp_ctx = talloc_new(module);
287         int ret;
288         NTSTATUS status;
289
290         ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
291                                     DSDB_FLAG_NEXT_MODULE |
292                                     DSDB_SEARCH_SHOW_RECYCLED |
293                                     DSDB_SEARCH_SHOW_EXTENDED_DN,
294                                     parent);
295         if (ret != LDB_SUCCESS) {
296                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
297                                        ldb_dn_get_linearized(dn));
298                 talloc_free(tmp_ctx);
299                 return ret;
300         }
301
302         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
303         if (!NT_STATUS_IS_OK(status)) {
304                 talloc_free(tmp_ctx);
305                 return ldb_operr(ldb_module_get_ctx(module));
306         }
307
308         talloc_free(tmp_ctx);
309         return LDB_SUCCESS;
310 }
311
312 /*
313   a ldb_modify request operating on modules below the
314   current module
315  */
316 int dsdb_module_modify(struct ldb_module *module,
317                        const struct ldb_message *message,
318                        uint32_t dsdb_flags,
319                        struct ldb_request *parent)
320 {
321         struct ldb_request *mod_req;
322         int ret;
323         struct ldb_context *ldb = ldb_module_get_ctx(module);
324         TALLOC_CTX *tmp_ctx = talloc_new(module);
325         struct ldb_result *res;
326
327         res = talloc_zero(tmp_ctx, struct ldb_result);
328         if (!res) {
329                 talloc_free(tmp_ctx);
330                 return ldb_oom(ldb_module_get_ctx(module));
331         }
332
333         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
334                                 message,
335                                 NULL,
336                                 res,
337                                 ldb_modify_default_callback,
338                                 parent);
339         LDB_REQ_SET_LOCATION(mod_req);
340         if (ret != LDB_SUCCESS) {
341                 talloc_free(tmp_ctx);
342                 return ret;
343         }
344
345         ret = dsdb_request_add_controls(mod_req, dsdb_flags);
346         if (ret != LDB_SUCCESS) {
347                 talloc_free(tmp_ctx);
348                 return ret;
349         }
350
351         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
352                 ldb_req_mark_trusted(mod_req);
353         }
354
355         /* Run the new request */
356         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
357                 ret = ldb_next_request(module, mod_req);
358         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
359                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
360         } else {
361                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
362                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
363                 ret = ops->modify(module, mod_req);
364         }
365         if (ret == LDB_SUCCESS) {
366                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
367         }
368
369         talloc_free(tmp_ctx);
370         return ret;
371 }
372
373
374
375 /*
376   a ldb_rename request operating on modules below the
377   current module
378  */
379 int dsdb_module_rename(struct ldb_module *module,
380                        struct ldb_dn *olddn, struct ldb_dn *newdn,
381                        uint32_t dsdb_flags,
382                        struct ldb_request *parent)
383 {
384         struct ldb_request *req;
385         int ret;
386         struct ldb_context *ldb = ldb_module_get_ctx(module);
387         TALLOC_CTX *tmp_ctx = talloc_new(module);
388         struct ldb_result *res;
389
390         res = talloc_zero(tmp_ctx, struct ldb_result);
391         if (!res) {
392                 talloc_free(tmp_ctx);
393                 return ldb_oom(ldb_module_get_ctx(module));
394         }
395
396         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
397                                    olddn,
398                                    newdn,
399                                    NULL,
400                                    res,
401                                    ldb_modify_default_callback,
402                                    parent);
403         LDB_REQ_SET_LOCATION(req);
404         if (ret != LDB_SUCCESS) {
405                 talloc_free(tmp_ctx);
406                 return ret;
407         }
408
409         ret = dsdb_request_add_controls(req, dsdb_flags);
410         if (ret != LDB_SUCCESS) {
411                 talloc_free(tmp_ctx);
412                 return ret;
413         }
414
415         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
416                 ldb_req_mark_trusted(req);
417         }
418
419         /* Run the new request */
420         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
421                 ret = ldb_next_request(module, req);
422         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
423                 ret = ldb_request(ldb_module_get_ctx(module), req);
424         } else {
425                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
426                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
427                 ret = ops->rename(module, req);
428         }
429         if (ret == LDB_SUCCESS) {
430                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
431         }
432
433         talloc_free(tmp_ctx);
434         return ret;
435 }
436
437 /*
438   a ldb_add request operating on modules below the
439   current module
440  */
441 int dsdb_module_add(struct ldb_module *module,
442                     const struct ldb_message *message,
443                     uint32_t dsdb_flags,
444                     struct ldb_request *parent)
445 {
446         struct ldb_request *req;
447         int ret;
448         struct ldb_context *ldb = ldb_module_get_ctx(module);
449         TALLOC_CTX *tmp_ctx = talloc_new(module);
450         struct ldb_result *res;
451
452         res = talloc_zero(tmp_ctx, struct ldb_result);
453         if (!res) {
454                 talloc_free(tmp_ctx);
455                 return ldb_oom(ldb_module_get_ctx(module));
456         }
457
458         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
459                                 message,
460                                 NULL,
461                                 res,
462                                 ldb_modify_default_callback,
463                                 parent);
464         LDB_REQ_SET_LOCATION(req);
465         if (ret != LDB_SUCCESS) {
466                 talloc_free(tmp_ctx);
467                 return ret;
468         }
469
470         ret = dsdb_request_add_controls(req, dsdb_flags);
471         if (ret != LDB_SUCCESS) {
472                 talloc_free(tmp_ctx);
473                 return ret;
474         }
475
476         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
477                 ldb_req_mark_trusted(req);
478         }
479
480         /* Run the new request */
481         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
482                 ret = ldb_next_request(module, req);
483         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
484                 ret = ldb_request(ldb_module_get_ctx(module), req);
485         } else {
486                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
487                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
488                 ret = ops->add(module, req);
489         }
490         if (ret == LDB_SUCCESS) {
491                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
492         }
493
494         talloc_free(tmp_ctx);
495         return ret;
496 }
497
498 /*
499   a ldb_delete request operating on modules below the
500   current module
501  */
502 int dsdb_module_del(struct ldb_module *module,
503                     struct ldb_dn *dn,
504                     uint32_t dsdb_flags,
505                     struct ldb_request *parent)
506 {
507         struct ldb_request *req;
508         int ret;
509         struct ldb_context *ldb = ldb_module_get_ctx(module);
510         TALLOC_CTX *tmp_ctx = talloc_new(module);
511         struct ldb_result *res;
512
513         res = talloc_zero(tmp_ctx, struct ldb_result);
514         if (!res) {
515                 talloc_free(tmp_ctx);
516                 return ldb_oom(ldb);
517         }
518
519         ret = ldb_build_del_req(&req, ldb, tmp_ctx,
520                                 dn,
521                                 NULL,
522                                 res,
523                                 ldb_modify_default_callback,
524                                 parent);
525         LDB_REQ_SET_LOCATION(req);
526         if (ret != LDB_SUCCESS) {
527                 talloc_free(tmp_ctx);
528                 return ret;
529         }
530
531         ret = dsdb_request_add_controls(req, dsdb_flags);
532         if (ret != LDB_SUCCESS) {
533                 talloc_free(tmp_ctx);
534                 return ret;
535         }
536
537         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
538                 ldb_req_mark_trusted(req);
539         }
540
541         /* Run the new request */
542         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
543                 ret = ldb_next_request(module, req);
544         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
545                 ret = ldb_request(ldb_module_get_ctx(module), req);
546         } else {
547                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
548                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
549                 ret = ops->del(module, req);
550         }
551         if (ret == LDB_SUCCESS) {
552                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
553         }
554
555         talloc_free(tmp_ctx);
556         return ret;
557 }
558
559 /*
560   check if a single valued link has multiple non-deleted values
561
562   This is needed when we will be using the RELAX control to stop
563   ldb_tdb from checking single valued links
564  */
565 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
566                                   const struct ldb_message_element *el)
567 {
568         bool found_active = false;
569         unsigned int i;
570
571         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
572             el->num_values < 2) {
573                 return LDB_SUCCESS;
574         }
575
576         for (i=0; i<el->num_values; i++) {
577                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
578                         if (found_active) {
579                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
580                         }
581                         found_active = true;
582                 }
583         }
584
585         return LDB_SUCCESS;
586 }
587
588 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
589                                         struct GUID op_feature_guid, bool *feature_enabled)
590 {
591         TALLOC_CTX *tmp_ctx;
592         struct ldb_context *ldb = ldb_module_get_ctx(module);
593         struct ldb_result *res;
594         struct ldb_dn *search_dn;
595         struct GUID search_guid;
596         const char *attrs[] = {"msDS-EnabledFeature", NULL};
597         int ret;
598         unsigned int i;
599         struct ldb_message_element *el;
600
601         *feature_enabled = false;
602
603         tmp_ctx = talloc_new(ldb);
604
605         ret = ldb_search(ldb, tmp_ctx, &res,
606                                         scope, LDB_SCOPE_BASE, attrs,
607                                         NULL);
608         if (ret != LDB_SUCCESS) {
609                 ldb_asprintf_errstring(ldb,
610                                 "Could no find the scope object - dn: %s\n",
611                                 ldb_dn_get_linearized(scope));
612                 talloc_free(tmp_ctx);
613                 return LDB_ERR_OPERATIONS_ERROR;
614         }
615         if (res->msgs[0]->num_elements > 0) {
616
617                 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
618
619                 attrs[0] = "msDS-OptionalFeatureGUID";
620
621                 for (i=0; i<el->num_values; i++) {
622                         search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
623
624                         ret = ldb_search(ldb, tmp_ctx, &res,
625                                                         search_dn, LDB_SCOPE_BASE, attrs,
626                                                         NULL);
627                         if (ret != LDB_SUCCESS) {
628                                 ldb_asprintf_errstring(ldb,
629                                                 "Could no find object dn: %s\n",
630                                                 ldb_dn_get_linearized(search_dn));
631                                 talloc_free(tmp_ctx);
632                                 return LDB_ERR_OPERATIONS_ERROR;
633                         }
634
635                         search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
636
637                         if (GUID_compare(&search_guid, &op_feature_guid) == 0){
638                                 *feature_enabled = true;
639                                 break;
640                         }
641                 }
642         }
643         talloc_free(tmp_ctx);
644         return LDB_SUCCESS;
645 }
646
647 /*
648   find the NTDS GUID from a computers DN record
649  */
650 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
651                                            TALLOC_CTX *mem_ctx,
652                                            struct ldb_dn *computer_dn,
653                                            struct GUID *ntds_guid,
654                                            struct ldb_request *parent)
655 {
656         int ret;
657         struct ldb_dn *dn;
658
659         *ntds_guid = GUID_zero();
660
661         ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
662                                        "serverReferenceBL", &dn, parent);
663         if (ret != LDB_SUCCESS) {
664                 return ret;
665         }
666
667         if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
668                 talloc_free(dn);
669                 return LDB_ERR_OPERATIONS_ERROR;
670         }
671
672         ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
673         talloc_free(dn);
674         return ret;
675 }
676
677 /*
678   find a 'reference' DN that points at another object
679   (eg. serverReference, rIDManagerReference etc)
680  */
681 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
682                              const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
683 {
684         const char *attrs[2];
685         struct ldb_result *res;
686         int ret;
687
688         attrs[0] = attribute;
689         attrs[1] = NULL;
690
691         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
692                                     DSDB_FLAG_NEXT_MODULE, parent);
693         if (ret != LDB_SUCCESS) {
694                 return ret;
695         }
696
697         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
698                                       mem_ctx, res->msgs[0], attribute);
699         if (!*dn) {
700                 ldb_reset_err_string(ldb_module_get_ctx(module));
701                 talloc_free(res);
702                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
703         }
704
705         talloc_free(res);
706         return LDB_SUCCESS;
707 }
708
709 /*
710   find the RID Manager$ DN via the rIDManagerReference attribute in the
711   base DN
712  */
713 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
714                                struct ldb_request *parent)
715 {
716         return dsdb_module_reference_dn(module, mem_ctx,
717                                         ldb_get_default_basedn(ldb_module_get_ctx(module)),
718                                         "rIDManagerReference", dn, parent);
719 }
720
721 /*
722   used to chain to the callers callback
723  */
724 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
725 {
726         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
727
728         talloc_steal(up_req, req);
729         return up_req->callback(up_req, ares);
730 }
731
732 /*
733   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
734   object for a partition
735  */
736 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
737                                    uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
738 {
739         struct ldb_context *ldb = ldb_module_get_ctx(module);
740         struct ldb_request *req;
741         int ret;
742         TALLOC_CTX *tmp_ctx = talloc_new(module);
743         struct dsdb_control_current_partition *p_ctrl;
744         struct ldb_result *res;
745
746         res = talloc_zero(tmp_ctx, struct ldb_result);
747         if (!res) {
748                 talloc_free(tmp_ctx);
749                 return ldb_module_oom(module);
750         }
751
752         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
753                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
754                                    LDB_SCOPE_BASE,
755                                    NULL, NULL,
756                                    NULL,
757                                    res, ldb_search_default_callback,
758                                    parent);
759         LDB_REQ_SET_LOCATION(req);
760         if (ret != LDB_SUCCESS) {
761                 talloc_free(tmp_ctx);
762                 return ret;
763         }
764
765         p_ctrl = talloc(req, struct dsdb_control_current_partition);
766         if (p_ctrl == NULL) {
767                 talloc_free(tmp_ctx);
768                 return ldb_module_oom(module);
769         }
770         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
771         p_ctrl->dn = dn;
772
773
774         ret = ldb_request_add_control(req,
775                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
776                                       false, p_ctrl);
777         if (ret != LDB_SUCCESS) {
778                 talloc_free(tmp_ctx);
779                 return ret;
780         }
781
782         /* Run the new request */
783         ret = ldb_next_request(module, req);
784
785         if (ret == LDB_SUCCESS) {
786                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
787         }
788
789         if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
790                 /* it hasn't been created yet, which means
791                    an implicit value of zero */
792                 *uSN = 0;
793                 talloc_free(tmp_ctx);
794                 ldb_reset_err_string(ldb);
795                 return LDB_SUCCESS;
796         }
797
798         if (ret != LDB_SUCCESS) {
799                 talloc_free(tmp_ctx);
800                 return ret;
801         }
802
803         if (res->count != 1) {
804                 *uSN = 0;
805                 if (urgent_uSN) {
806                         *urgent_uSN = 0;
807                 }
808         } else {
809                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
810                 if (urgent_uSN) {
811                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
812                 }
813         }
814
815         talloc_free(tmp_ctx);
816
817         return LDB_SUCCESS;
818 }
819
820 /*
821   save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
822   partition
823  */
824 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
825                                    uint64_t uSN, uint64_t urgent_uSN,
826                                    struct ldb_request *parent)
827 {
828         struct ldb_context *ldb = ldb_module_get_ctx(module);
829         struct ldb_request *req;
830         struct ldb_message *msg;
831         struct dsdb_control_current_partition *p_ctrl;
832         int ret;
833         struct ldb_result *res;
834
835         msg = ldb_msg_new(module);
836         if (msg == NULL) {
837                 return ldb_module_oom(module);
838         }
839
840         msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
841         if (msg->dn == NULL) {
842                 talloc_free(msg);
843                 return ldb_operr(ldb_module_get_ctx(module));
844         }
845
846         res = talloc_zero(msg, struct ldb_result);
847         if (!res) {
848                 talloc_free(msg);
849                 return ldb_module_oom(module);
850         }
851
852         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
853         if (ret != LDB_SUCCESS) {
854                 talloc_free(msg);
855                 return ret;
856         }
857         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
858
859         /* urgent_uSN is optional so may not be stored */
860         if (urgent_uSN) {
861                 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
862                                            urgent_uSN);
863                 if (ret != LDB_SUCCESS) {
864                         talloc_free(msg);
865                         return ret;
866                 }
867                 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
868         }
869
870
871         p_ctrl = talloc(msg, struct dsdb_control_current_partition);
872         if (p_ctrl == NULL) {
873                 talloc_free(msg);
874                 return ldb_oom(ldb);
875         }
876         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
877         p_ctrl->dn = dn;
878         ret = ldb_build_mod_req(&req, ldb, msg,
879                                 msg,
880                                 NULL,
881                                 res,
882                                 ldb_modify_default_callback,
883                                 parent);
884         LDB_REQ_SET_LOCATION(req);
885 again:
886         if (ret != LDB_SUCCESS) {
887                 talloc_free(msg);
888                 return ret;
889         }
890
891         ret = ldb_request_add_control(req,
892                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
893                                       false, p_ctrl);
894         if (ret != LDB_SUCCESS) {
895                 talloc_free(msg);
896                 return ret;
897         }
898
899         /* Run the new request */
900         ret = ldb_next_request(module, req);
901
902         if (ret == LDB_SUCCESS) {
903                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
904         }
905         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
906                 ret = ldb_build_add_req(&req, ldb, msg,
907                                         msg,
908                                         NULL,
909                                         res,
910                                         ldb_modify_default_callback,
911                                         parent);
912                 LDB_REQ_SET_LOCATION(req);
913                 goto again;
914         }
915
916         talloc_free(msg);
917
918         return ret;
919 }
920
921 bool dsdb_module_am_system(struct ldb_module *module)
922 {
923         struct ldb_context *ldb = ldb_module_get_ctx(module);
924         struct auth_session_info *session_info
925                 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
926         return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
927 }
928
929 bool dsdb_module_am_administrator(struct ldb_module *module)
930 {
931         struct ldb_context *ldb = ldb_module_get_ctx(module);
932         struct auth_session_info *session_info
933                 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
934         return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
935 }
936
937 /*
938   check if the recyclebin is enabled
939  */
940 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
941 {
942         struct ldb_context *ldb = ldb_module_get_ctx(module);
943         struct ldb_dn *partitions_dn;
944         struct GUID recyclebin_guid;
945         int ret;
946
947         partitions_dn = samdb_partitions_dn(ldb, module);
948
949         GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
950
951         ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
952         if (ret != LDB_SUCCESS) {
953                 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
954                 talloc_free(partitions_dn);
955                 return LDB_ERR_UNWILLING_TO_PERFORM;
956         }
957
958         talloc_free(partitions_dn);
959         return LDB_SUCCESS;
960 }
961
962 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
963                                        struct ldb_message *msg,
964                                        const char *attr,
965                                        const int32_t *old_val,
966                                        const int32_t *new_val)
967 {
968         struct ldb_message_element *el;
969         int ret;
970         char *vstring;
971
972         if (old_val) {
973                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
974                 if (ret != LDB_SUCCESS) {
975                         return ret;
976                 }
977                 el->num_values = 1;
978                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
979                 if (!el->values) {
980                         return ldb_module_oom(module);
981                 }
982                 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
983                 if (!vstring) {
984                         return ldb_module_oom(module);
985                 }
986                 *el->values = data_blob_string_const(vstring);
987         }
988
989         if (new_val) {
990                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
991                 if (ret != LDB_SUCCESS) {
992                         return ret;
993                 }
994                 el->num_values = 1;
995                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
996                 if (!el->values) {
997                         return ldb_module_oom(module);
998                 }
999                 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1000                 if (!vstring) {
1001                         return ldb_module_oom(module);
1002                 }
1003                 *el->values = data_blob_string_const(vstring);
1004         }
1005
1006         return LDB_SUCCESS;
1007 }
1008
1009 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1010                                         struct ldb_message *msg,
1011                                         const char *attr,
1012                                         const uint32_t *old_val,
1013                                         const uint32_t *new_val)
1014 {
1015         return dsdb_msg_constrainted_update_int32(module, msg, attr,
1016                                                   (const int32_t *)old_val,
1017                                                   (const int32_t *)new_val);
1018 }
1019
1020 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1021                                        struct ldb_message *msg,
1022                                        const char *attr,
1023                                        const int64_t *old_val,
1024                                        const int64_t *new_val)
1025 {
1026         struct ldb_message_element *el;
1027         int ret;
1028         char *vstring;
1029
1030         if (old_val) {
1031                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1032                 if (ret != LDB_SUCCESS) {
1033                         return ret;
1034                 }
1035                 el->num_values = 1;
1036                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1037                 if (!el->values) {
1038                         return ldb_module_oom(module);
1039                 }
1040                 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1041                 if (!vstring) {
1042                         return ldb_module_oom(module);
1043                 }
1044                 *el->values = data_blob_string_const(vstring);
1045         }
1046
1047         if (new_val) {
1048                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1049                 if (ret != LDB_SUCCESS) {
1050                         return ret;
1051                 }
1052                 el->num_values = 1;
1053                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1054                 if (!el->values) {
1055                         return ldb_module_oom(module);
1056                 }
1057                 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1058                 if (!vstring) {
1059                         return ldb_module_oom(module);
1060                 }
1061                 *el->values = data_blob_string_const(vstring);
1062         }
1063
1064         return LDB_SUCCESS;
1065 }
1066
1067 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1068                                         struct ldb_message *msg,
1069                                         const char *attr,
1070                                         const uint64_t *old_val,
1071                                         const uint64_t *new_val)
1072 {
1073         return dsdb_msg_constrainted_update_int64(module, msg, attr,
1074                                                   (const int64_t *)old_val,
1075                                                   (const int64_t *)new_val);
1076 }
1077
1078 /*
1079   update an int32 attribute safely via a constrained delete/add
1080  */
1081 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1082                                           struct ldb_dn *dn,
1083                                           const char *attr,
1084                                           const int32_t *old_val,
1085                                           const int32_t *new_val,
1086                                           struct ldb_request *parent)
1087 {
1088         struct ldb_message *msg;
1089         int ret;
1090
1091         msg = ldb_msg_new(module);
1092         msg->dn = dn;
1093
1094         ret = dsdb_msg_constrainted_update_int32(module,
1095                                                  msg, attr,
1096                                                  old_val,
1097                                                  new_val);
1098         if (ret != LDB_SUCCESS) {
1099                 talloc_free(msg);
1100                 return ret;
1101         }
1102
1103         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1104         talloc_free(msg);
1105         return ret;
1106 }
1107
1108 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1109                                            struct ldb_dn *dn,
1110                                            const char *attr,
1111                                            const uint32_t *old_val,
1112                                            const uint32_t *new_val,
1113                                            struct ldb_request *parent)
1114 {
1115         return dsdb_module_constrainted_update_int32(module, dn, attr,
1116                                                      (const int32_t *)old_val,
1117                                                      (const int32_t *)new_val, parent);
1118 }
1119
1120 /*
1121   update an int64 attribute safely via a constrained delete/add
1122  */
1123 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1124                                           struct ldb_dn *dn,
1125                                           const char *attr,
1126                                           const int64_t *old_val,
1127                                           const int64_t *new_val,
1128                                           struct ldb_request *parent)
1129 {
1130         struct ldb_message *msg;
1131         int ret;
1132
1133         msg = ldb_msg_new(module);
1134         msg->dn = dn;
1135
1136         ret = dsdb_msg_constrainted_update_int64(module,
1137                                                  msg, attr,
1138                                                  old_val,
1139                                                  new_val);
1140         if (ret != LDB_SUCCESS) {
1141                 talloc_free(msg);
1142                 return ret;
1143         }
1144
1145         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1146         talloc_free(msg);
1147         return ret;
1148 }
1149
1150 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1151                                            struct ldb_dn *dn,
1152                                            const char *attr,
1153                                            const uint64_t *old_val,
1154                                            const uint64_t *new_val,
1155                                            struct ldb_request *parent)
1156 {
1157         return dsdb_module_constrainted_update_int64(module, dn, attr,
1158                                                      (const int64_t *)old_val,
1159                                                      (const int64_t *)new_val,
1160                                                      parent);
1161 }
1162
1163
1164 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1165                                                     TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1166 {
1167         int ret;
1168         struct ldb_dn *new_dn;
1169         struct ldb_context *ldb = ldb_module_get_ctx(module);
1170         static const char *attrs[] = { "dSHeuristics", NULL };
1171         struct ldb_result *res;
1172
1173         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1174         if (!ldb_dn_add_child_fmt(new_dn,
1175                                    "CN=Directory Service,CN=Windows NT,CN=Services")) {
1176                 talloc_free(new_dn);
1177                 return NULL;
1178         }
1179         ret = dsdb_module_search_dn(module, mem_ctx, &res,
1180                                     new_dn,
1181                                     attrs,
1182                                     DSDB_FLAG_NEXT_MODULE,
1183                                     parent);
1184         if (ret == LDB_SUCCESS && res->count == 1) {
1185                 talloc_free(new_dn);
1186                 return ldb_msg_find_ldb_val(res->msgs[0],
1187                                             "dSHeuristics");
1188         }
1189         talloc_free(new_dn);
1190         return NULL;
1191 }
1192
1193 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1194 {
1195         TALLOC_CTX *tmp_ctx = talloc_new(module);
1196         bool result;
1197         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1198                                                                      tmp_ctx, parent);
1199         if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1200                 result = true;
1201         } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1202                 result = false;
1203         } else {
1204                 result = true;
1205         }
1206
1207         talloc_free(tmp_ctx);
1208         return result;
1209 }
1210
1211 bool dsdb_user_password_support(struct ldb_module *module,
1212                                 TALLOC_CTX *mem_ctx,
1213                                 struct ldb_request *parent)
1214 {
1215         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1216         bool result;
1217         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1218                                                                      tmp_ctx,
1219                                                                      parent);
1220         if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1221                 result = false;
1222         } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1223                    (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1224                 result = false;
1225         } else {
1226                 result = true;
1227         }
1228
1229         talloc_free(tmp_ctx);
1230         return result;
1231 }
1232
1233 /*
1234   show the chain of requests, useful for debugging async requests
1235  */
1236 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1237 {
1238         char *s = ldb_module_call_chain(req, req);
1239         DEBUG(level, ("%s\n", s));
1240         talloc_free(s);
1241 }
1242
1243 /*
1244  * Gets back a single-valued attribute by the rules of the DSDB triggers when
1245  * performing a modify operation.
1246  *
1247  * In order that the constraint checking by the "objectclass_attrs" LDB module
1248  * does work properly, the change request should remain similar or only be
1249  * enhanced (no other modifications as deletions, variations).
1250  */
1251 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1252                                                         const char *attr_name,
1253                                                         enum ldb_request_type operation)
1254 {
1255         struct ldb_message_element *el = NULL;
1256         unsigned int i;
1257
1258         /* We've to walk over all modification entries and consider the last
1259          * non-delete one which belongs to "attr_name".
1260          *
1261          * If "el" is NULL afterwards then that means there was no interesting
1262          * change entry. */
1263         for (i = 0; i < msg->num_elements; i++) {
1264                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1265                         if ((operation == LDB_MODIFY) &&
1266                             (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1267                                                 == LDB_FLAG_MOD_DELETE)) {
1268                                 continue;
1269                         }
1270                         el = &msg->elements[i];
1271                 }
1272         }
1273
1274         return el;
1275 }