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