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