s4-selftest: add unit tests for sites's function in python
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / util.c
blobcee9ac0d00a78750344158746c836d9a8a2c79e9
1 /*
2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 2009
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7 Copyright (C) Matthieu Patou <mat@matws.net> 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "ldb.h"
25 #include "ldb_module.h"
26 #include "librpc/ndr/libndr.h"
27 #include "dsdb/samdb/ldb_modules/util.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "dsdb/common/util.h"
30 #include "libcli/security/security.h"
33 search for attrs on one DN, in the modules below
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)
43 int ret;
44 struct ldb_request *req;
45 TALLOC_CTX *tmp_ctx;
46 struct ldb_result *res;
48 tmp_ctx = talloc_new(mem_ctx);
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));
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;
71 ret = dsdb_request_add_controls(req, dsdb_flags);
72 if (ret != LDB_SUCCESS) {
73 talloc_free(tmp_ctx);
74 return ret;
77 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
78 ldb_req_mark_trusted(req);
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);
91 if (ret == LDB_SUCCESS) {
92 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
95 if (ret != LDB_SUCCESS) {
96 talloc_free(tmp_ctx);
97 return ret;
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);
109 talloc_free(tmp_ctx);
110 return ret;
113 int dsdb_module_search_tree(struct ldb_module *module,
114 TALLOC_CTX *mem_ctx,
115 struct ldb_result **_res,
116 struct ldb_dn *basedn,
117 enum ldb_scope scope,
118 struct ldb_parse_tree *tree,
119 const char * const *attrs,
120 int dsdb_flags,
121 struct ldb_request *parent)
123 int ret;
124 struct ldb_request *req;
125 TALLOC_CTX *tmp_ctx;
126 struct ldb_result *res;
128 tmp_ctx = talloc_new(mem_ctx);
130 /* cross-partitions searches with a basedn break multi-domain support */
131 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
133 res = talloc_zero(tmp_ctx, struct ldb_result);
134 if (!res) {
135 talloc_free(tmp_ctx);
136 return ldb_oom(ldb_module_get_ctx(module));
139 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
140 basedn,
141 scope,
142 tree,
143 attrs,
144 NULL,
145 res,
146 ldb_search_default_callback,
147 parent);
148 LDB_REQ_SET_LOCATION(req);
149 if (ret != LDB_SUCCESS) {
150 talloc_free(tmp_ctx);
151 return ret;
154 ret = dsdb_request_add_controls(req, dsdb_flags);
155 if (ret != LDB_SUCCESS) {
156 talloc_free(tmp_ctx);
157 return ret;
160 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
161 ldb_req_mark_trusted(req);
164 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
165 ret = ldb_next_request(module, req);
166 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
167 ret = ldb_request(ldb_module_get_ctx(module), req);
168 } else {
169 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
170 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
171 ret = ops->search(module, req);
173 if (ret == LDB_SUCCESS) {
174 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
177 talloc_free(req);
178 if (ret == LDB_SUCCESS) {
179 *_res = talloc_steal(mem_ctx, res);
181 talloc_free(tmp_ctx);
182 return ret;
186 search for attrs in the modules below
188 int dsdb_module_search(struct ldb_module *module,
189 TALLOC_CTX *mem_ctx,
190 struct ldb_result **_res,
191 struct ldb_dn *basedn, enum ldb_scope scope,
192 const char * const *attrs,
193 int dsdb_flags,
194 struct ldb_request *parent,
195 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
197 int ret;
198 TALLOC_CTX *tmp_ctx;
199 va_list ap;
200 char *expression;
201 struct ldb_parse_tree *tree;
203 /* cross-partitions searches with a basedn break multi-domain support */
204 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
206 tmp_ctx = talloc_new(mem_ctx);
208 if (format) {
209 va_start(ap, format);
210 expression = talloc_vasprintf(tmp_ctx, format, ap);
211 va_end(ap);
213 if (!expression) {
214 talloc_free(tmp_ctx);
215 return ldb_oom(ldb_module_get_ctx(module));
217 } else {
218 expression = NULL;
221 tree = ldb_parse_tree(tmp_ctx, expression);
222 if (tree == NULL) {
223 talloc_free(tmp_ctx);
224 ldb_set_errstring(ldb_module_get_ctx(module),
225 "Unable to parse search expression");
226 return LDB_ERR_OPERATIONS_ERROR;
229 ret = dsdb_module_search_tree(module,
230 mem_ctx,
231 _res,
232 basedn,
233 scope,
234 tree,
235 attrs,
236 dsdb_flags,
237 parent);
239 talloc_free(tmp_ctx);
240 return ret;
244 find a DN given a GUID. This searches across all partitions
246 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
247 const struct GUID *guid, struct ldb_dn **dn,
248 struct ldb_request *parent)
250 struct ldb_result *res;
251 const char *attrs[] = { NULL };
252 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
253 int ret;
255 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
256 attrs,
257 DSDB_FLAG_NEXT_MODULE |
258 DSDB_SEARCH_SHOW_RECYCLED |
259 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
260 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
261 parent,
262 "objectGUID=%s", GUID_string(tmp_ctx, guid));
263 if (ret != LDB_SUCCESS) {
264 talloc_free(tmp_ctx);
265 return ret;
267 if (res->count == 0) {
268 talloc_free(tmp_ctx);
269 return LDB_ERR_NO_SUCH_OBJECT;
271 if (res->count != 1) {
272 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
273 GUID_string(tmp_ctx, guid));
274 talloc_free(tmp_ctx);
275 return LDB_ERR_OPERATIONS_ERROR;
278 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
280 talloc_free(tmp_ctx);
281 return LDB_SUCCESS;
285 find a GUID given a DN.
287 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
288 struct ldb_request *parent)
290 const char *attrs[] = { NULL };
291 struct ldb_result *res;
292 TALLOC_CTX *tmp_ctx = talloc_new(module);
293 int ret;
294 NTSTATUS status;
296 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
297 DSDB_FLAG_NEXT_MODULE |
298 DSDB_SEARCH_SHOW_RECYCLED |
299 DSDB_SEARCH_SHOW_EXTENDED_DN,
300 parent);
301 if (ret != LDB_SUCCESS) {
302 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
303 ldb_dn_get_linearized(dn));
304 talloc_free(tmp_ctx);
305 return ret;
308 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
309 if (!NT_STATUS_IS_OK(status)) {
310 talloc_free(tmp_ctx);
311 return ldb_operr(ldb_module_get_ctx(module));
314 talloc_free(tmp_ctx);
315 return LDB_SUCCESS;
318 a ldb_extended request operating on modules below the
319 current module
321 int dsdb_module_extended(struct ldb_module *module,
322 const char* oid, void* data,
323 uint32_t dsdb_flags,
324 struct ldb_request *parent)
326 struct ldb_request *req;
327 int ret;
328 struct ldb_context *ldb = ldb_module_get_ctx(module);
329 TALLOC_CTX *tmp_ctx = talloc_new(module);
330 struct ldb_result *res;
332 res = talloc_zero(tmp_ctx, struct ldb_result);
333 if (!res) {
334 talloc_free(tmp_ctx);
335 return ldb_oom(ldb_module_get_ctx(module));
338 ret = ldb_build_extended_req(&req, ldb,
339 tmp_ctx,
340 oid,
341 data,
342 NULL,
343 res, ldb_extended_default_callback,
344 parent);
346 LDB_REQ_SET_LOCATION(req);
347 if (ret != LDB_SUCCESS) {
348 talloc_free(tmp_ctx);
349 return ret;
352 ret = dsdb_request_add_controls(req, dsdb_flags);
353 if (ret != LDB_SUCCESS) {
354 talloc_free(tmp_ctx);
355 return ret;
358 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
359 ldb_req_mark_trusted(req);
362 /* Run the new request */
363 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
364 ret = ldb_next_request(module, req);
365 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
366 ret = ldb_request(ldb_module_get_ctx(module), req);
367 } else {
368 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
369 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
370 ret = ops->extended(module, req);
372 if (ret == LDB_SUCCESS) {
373 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
376 talloc_free(tmp_ctx);
377 return ret;
380 a ldb_modify request operating on modules below the
381 current module
383 int dsdb_module_modify(struct ldb_module *module,
384 const struct ldb_message *message,
385 uint32_t dsdb_flags,
386 struct ldb_request *parent)
388 struct ldb_request *mod_req;
389 int ret;
390 struct ldb_context *ldb = ldb_module_get_ctx(module);
391 TALLOC_CTX *tmp_ctx = talloc_new(module);
392 struct ldb_result *res;
394 res = talloc_zero(tmp_ctx, struct ldb_result);
395 if (!res) {
396 talloc_free(tmp_ctx);
397 return ldb_oom(ldb_module_get_ctx(module));
400 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
401 message,
402 NULL,
403 res,
404 ldb_modify_default_callback,
405 parent);
406 LDB_REQ_SET_LOCATION(mod_req);
407 if (ret != LDB_SUCCESS) {
408 talloc_free(tmp_ctx);
409 return ret;
412 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
413 if (ret != LDB_SUCCESS) {
414 talloc_free(tmp_ctx);
415 return ret;
418 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
419 ldb_req_mark_trusted(mod_req);
422 /* Run the new request */
423 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
424 ret = ldb_next_request(module, mod_req);
425 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
426 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
427 } else {
428 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
429 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
430 ret = ops->modify(module, mod_req);
432 if (ret == LDB_SUCCESS) {
433 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
436 talloc_free(tmp_ctx);
437 return ret;
443 a ldb_rename request operating on modules below the
444 current module
446 int dsdb_module_rename(struct ldb_module *module,
447 struct ldb_dn *olddn, struct ldb_dn *newdn,
448 uint32_t dsdb_flags,
449 struct ldb_request *parent)
451 struct ldb_request *req;
452 int ret;
453 struct ldb_context *ldb = ldb_module_get_ctx(module);
454 TALLOC_CTX *tmp_ctx = talloc_new(module);
455 struct ldb_result *res;
457 res = talloc_zero(tmp_ctx, struct ldb_result);
458 if (!res) {
459 talloc_free(tmp_ctx);
460 return ldb_oom(ldb_module_get_ctx(module));
463 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
464 olddn,
465 newdn,
466 NULL,
467 res,
468 ldb_modify_default_callback,
469 parent);
470 LDB_REQ_SET_LOCATION(req);
471 if (ret != LDB_SUCCESS) {
472 talloc_free(tmp_ctx);
473 return ret;
476 ret = dsdb_request_add_controls(req, dsdb_flags);
477 if (ret != LDB_SUCCESS) {
478 talloc_free(tmp_ctx);
479 return ret;
482 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
483 ldb_req_mark_trusted(req);
486 /* Run the new request */
487 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
488 ret = ldb_next_request(module, req);
489 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
490 ret = ldb_request(ldb_module_get_ctx(module), req);
491 } else {
492 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
493 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
494 ret = ops->rename(module, req);
496 if (ret == LDB_SUCCESS) {
497 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
500 talloc_free(tmp_ctx);
501 return ret;
505 a ldb_add request operating on modules below the
506 current module
508 int dsdb_module_add(struct ldb_module *module,
509 const struct ldb_message *message,
510 uint32_t dsdb_flags,
511 struct ldb_request *parent)
513 struct ldb_request *req;
514 int ret;
515 struct ldb_context *ldb = ldb_module_get_ctx(module);
516 TALLOC_CTX *tmp_ctx = talloc_new(module);
517 struct ldb_result *res;
519 res = talloc_zero(tmp_ctx, struct ldb_result);
520 if (!res) {
521 talloc_free(tmp_ctx);
522 return ldb_oom(ldb_module_get_ctx(module));
525 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
526 message,
527 NULL,
528 res,
529 ldb_modify_default_callback,
530 parent);
531 LDB_REQ_SET_LOCATION(req);
532 if (ret != LDB_SUCCESS) {
533 talloc_free(tmp_ctx);
534 return ret;
537 ret = dsdb_request_add_controls(req, dsdb_flags);
538 if (ret != LDB_SUCCESS) {
539 talloc_free(tmp_ctx);
540 return ret;
543 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
544 ldb_req_mark_trusted(req);
547 /* Run the new request */
548 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
549 ret = ldb_next_request(module, req);
550 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
551 ret = ldb_request(ldb_module_get_ctx(module), req);
552 } else {
553 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
554 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
555 ret = ops->add(module, req);
557 if (ret == LDB_SUCCESS) {
558 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
561 talloc_free(tmp_ctx);
562 return ret;
566 a ldb_delete request operating on modules below the
567 current module
569 int dsdb_module_del(struct ldb_module *module,
570 struct ldb_dn *dn,
571 uint32_t dsdb_flags,
572 struct ldb_request *parent)
574 struct ldb_request *req;
575 int ret;
576 struct ldb_context *ldb = ldb_module_get_ctx(module);
577 TALLOC_CTX *tmp_ctx = talloc_new(module);
578 struct ldb_result *res;
580 res = talloc_zero(tmp_ctx, struct ldb_result);
581 if (!res) {
582 talloc_free(tmp_ctx);
583 return ldb_oom(ldb);
586 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
588 NULL,
589 res,
590 ldb_modify_default_callback,
591 parent);
592 LDB_REQ_SET_LOCATION(req);
593 if (ret != LDB_SUCCESS) {
594 talloc_free(tmp_ctx);
595 return ret;
598 ret = dsdb_request_add_controls(req, dsdb_flags);
599 if (ret != LDB_SUCCESS) {
600 talloc_free(tmp_ctx);
601 return ret;
604 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
605 ldb_req_mark_trusted(req);
608 /* Run the new request */
609 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
610 ret = ldb_next_request(module, req);
611 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
612 ret = ldb_request(ldb_module_get_ctx(module), req);
613 } else {
614 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
615 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
616 ret = ops->del(module, req);
618 if (ret == LDB_SUCCESS) {
619 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
622 talloc_free(tmp_ctx);
623 return ret;
627 check if a single valued link has multiple non-deleted values
629 This is needed when we will be using the RELAX control to stop
630 ldb_tdb from checking single valued links
632 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
633 const struct ldb_message_element *el)
635 bool found_active = false;
636 unsigned int i;
638 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
639 el->num_values < 2) {
640 return LDB_SUCCESS;
643 for (i=0; i<el->num_values; i++) {
644 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
645 if (found_active) {
646 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
648 found_active = true;
652 return LDB_SUCCESS;
656 check if an optional feature is enabled on our own NTDS DN
658 Note that features can be marked as enabled in more than one
659 place. For example, the recyclebin feature is marked as enabled both
660 on the CN=Partitions,CN=Configurration object and on the NTDS DN of
661 each DC in the forest. It seems likely that it is the job of the KCC
662 to propogate between the two
664 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
666 TALLOC_CTX *tmp_ctx;
667 struct ldb_context *ldb = ldb_module_get_ctx(module);
668 struct ldb_result *res;
669 struct ldb_dn *search_dn;
670 struct GUID search_guid;
671 const char *attrs[] = {"msDS-EnabledFeature", NULL};
672 int ret;
673 unsigned int i;
674 struct ldb_message_element *el;
675 struct ldb_dn *feature_dn;
677 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module));
678 if (feature_dn == NULL) {
679 return ldb_operr(ldb_module_get_ctx(module));
682 *feature_enabled = false;
684 tmp_ctx = talloc_new(ldb);
686 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
687 if (ret != LDB_SUCCESS) {
688 ldb_asprintf_errstring(ldb,
689 "Could not find the feature object - dn: %s\n",
690 ldb_dn_get_linearized(feature_dn));
691 talloc_free(tmp_ctx);
692 return LDB_ERR_OPERATIONS_ERROR;
694 if (res->msgs[0]->num_elements > 0) {
695 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
697 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
699 for (i=0; i<el->num_values; i++) {
700 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
702 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
703 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
704 if (ret != LDB_SUCCESS) {
705 ldb_asprintf_errstring(ldb,
706 "Could no find object dn: %s\n",
707 ldb_dn_get_linearized(search_dn));
708 talloc_free(tmp_ctx);
709 return LDB_ERR_OPERATIONS_ERROR;
712 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
714 if (GUID_compare(&search_guid, &op_feature_guid) == 0) {
715 *feature_enabled = true;
716 break;
720 talloc_free(tmp_ctx);
721 return LDB_SUCCESS;
725 find the NTDS GUID from a computers DN record
727 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
728 TALLOC_CTX *mem_ctx,
729 struct ldb_dn *computer_dn,
730 struct GUID *ntds_guid,
731 struct ldb_request *parent)
733 int ret;
734 struct ldb_dn *dn;
736 *ntds_guid = GUID_zero();
738 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
739 "serverReferenceBL", &dn, parent);
740 if (ret != LDB_SUCCESS) {
741 return ret;
744 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
745 talloc_free(dn);
746 return LDB_ERR_OPERATIONS_ERROR;
749 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
750 talloc_free(dn);
751 return ret;
755 find a 'reference' DN that points at another object
756 (eg. serverReference, rIDManagerReference etc)
758 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
759 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
761 const char *attrs[2];
762 struct ldb_result *res;
763 int ret;
765 attrs[0] = attribute;
766 attrs[1] = NULL;
768 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
769 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
770 if (ret != LDB_SUCCESS) {
771 return ret;
774 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
775 mem_ctx, res->msgs[0], attribute);
776 if (!*dn) {
777 ldb_reset_err_string(ldb_module_get_ctx(module));
778 talloc_free(res);
779 return LDB_ERR_NO_SUCH_ATTRIBUTE;
782 talloc_free(res);
783 return LDB_SUCCESS;
787 find the RID Manager$ DN via the rIDManagerReference attribute in the
788 base DN
790 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
791 struct ldb_request *parent)
793 return dsdb_module_reference_dn(module, mem_ctx,
794 ldb_get_default_basedn(ldb_module_get_ctx(module)),
795 "rIDManagerReference", dn, parent);
799 used to chain to the callers callback
801 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
803 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
805 talloc_steal(up_req, req);
806 return up_req->callback(up_req, ares);
810 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
811 object for a partition
813 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
814 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
816 struct ldb_context *ldb = ldb_module_get_ctx(module);
817 struct ldb_request *req;
818 int ret;
819 TALLOC_CTX *tmp_ctx = talloc_new(module);
820 struct dsdb_control_current_partition *p_ctrl;
821 struct ldb_result *res;
823 res = talloc_zero(tmp_ctx, struct ldb_result);
824 if (!res) {
825 talloc_free(tmp_ctx);
826 return ldb_module_oom(module);
829 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
830 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
831 LDB_SCOPE_BASE,
832 NULL, NULL,
833 NULL,
834 res, ldb_search_default_callback,
835 parent);
836 LDB_REQ_SET_LOCATION(req);
837 if (ret != LDB_SUCCESS) {
838 talloc_free(tmp_ctx);
839 return ret;
842 p_ctrl = talloc(req, struct dsdb_control_current_partition);
843 if (p_ctrl == NULL) {
844 talloc_free(tmp_ctx);
845 return ldb_module_oom(module);
847 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
848 p_ctrl->dn = dn;
851 ret = ldb_request_add_control(req,
852 DSDB_CONTROL_CURRENT_PARTITION_OID,
853 false, p_ctrl);
854 if (ret != LDB_SUCCESS) {
855 talloc_free(tmp_ctx);
856 return ret;
859 /* Run the new request */
860 ret = ldb_next_request(module, req);
862 if (ret == LDB_SUCCESS) {
863 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
866 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
867 /* it hasn't been created yet, which means
868 an implicit value of zero */
869 *uSN = 0;
870 talloc_free(tmp_ctx);
871 ldb_reset_err_string(ldb);
872 return LDB_SUCCESS;
875 if (ret != LDB_SUCCESS) {
876 talloc_free(tmp_ctx);
877 return ret;
880 if (res->count != 1) {
881 *uSN = 0;
882 if (urgent_uSN) {
883 *urgent_uSN = 0;
885 } else {
886 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
887 if (urgent_uSN) {
888 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
892 talloc_free(tmp_ctx);
894 return LDB_SUCCESS;
898 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
899 partition
901 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
902 uint64_t uSN, uint64_t urgent_uSN,
903 struct ldb_request *parent)
905 struct ldb_context *ldb = ldb_module_get_ctx(module);
906 struct ldb_request *req;
907 struct ldb_message *msg;
908 struct dsdb_control_current_partition *p_ctrl;
909 int ret;
910 struct ldb_result *res;
912 msg = ldb_msg_new(module);
913 if (msg == NULL) {
914 return ldb_module_oom(module);
917 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
918 if (msg->dn == NULL) {
919 talloc_free(msg);
920 return ldb_operr(ldb_module_get_ctx(module));
923 res = talloc_zero(msg, struct ldb_result);
924 if (!res) {
925 talloc_free(msg);
926 return ldb_module_oom(module);
929 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
930 if (ret != LDB_SUCCESS) {
931 talloc_free(msg);
932 return ret;
934 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
936 /* urgent_uSN is optional so may not be stored */
937 if (urgent_uSN) {
938 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
939 urgent_uSN);
940 if (ret != LDB_SUCCESS) {
941 talloc_free(msg);
942 return ret;
944 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
948 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
949 if (p_ctrl == NULL) {
950 talloc_free(msg);
951 return ldb_oom(ldb);
953 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
954 p_ctrl->dn = dn;
955 ret = ldb_build_mod_req(&req, ldb, msg,
956 msg,
957 NULL,
958 res,
959 ldb_modify_default_callback,
960 parent);
961 LDB_REQ_SET_LOCATION(req);
962 again:
963 if (ret != LDB_SUCCESS) {
964 talloc_free(msg);
965 return ret;
968 ret = ldb_request_add_control(req,
969 DSDB_CONTROL_CURRENT_PARTITION_OID,
970 false, p_ctrl);
971 if (ret != LDB_SUCCESS) {
972 talloc_free(msg);
973 return ret;
976 /* Run the new request */
977 ret = ldb_next_request(module, req);
979 if (ret == LDB_SUCCESS) {
980 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
982 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
983 ret = ldb_build_add_req(&req, ldb, msg,
984 msg,
985 NULL,
986 res,
987 ldb_modify_default_callback,
988 parent);
989 LDB_REQ_SET_LOCATION(req);
990 goto again;
993 talloc_free(msg);
995 return ret;
998 bool dsdb_module_am_system(struct ldb_module *module)
1000 struct ldb_context *ldb = ldb_module_get_ctx(module);
1001 struct auth_session_info *session_info
1002 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1003 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1006 bool dsdb_module_am_administrator(struct ldb_module *module)
1008 struct ldb_context *ldb = ldb_module_get_ctx(module);
1009 struct auth_session_info *session_info
1010 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1011 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1015 check if the recyclebin is enabled
1017 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1019 struct ldb_context *ldb = ldb_module_get_ctx(module);
1020 struct GUID recyclebin_guid;
1021 int ret;
1023 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1025 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1026 if (ret != LDB_SUCCESS) {
1027 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1028 return LDB_ERR_UNWILLING_TO_PERFORM;
1031 return LDB_SUCCESS;
1034 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1035 struct ldb_message *msg,
1036 const char *attr,
1037 const int32_t *old_val,
1038 const int32_t *new_val)
1040 struct ldb_message_element *el;
1041 int ret;
1042 char *vstring;
1044 if (old_val) {
1045 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1046 if (ret != LDB_SUCCESS) {
1047 return ret;
1049 el->num_values = 1;
1050 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1051 if (!el->values) {
1052 return ldb_module_oom(module);
1054 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1055 if (!vstring) {
1056 return ldb_module_oom(module);
1058 *el->values = data_blob_string_const(vstring);
1061 if (new_val) {
1062 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1063 if (ret != LDB_SUCCESS) {
1064 return ret;
1066 el->num_values = 1;
1067 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1068 if (!el->values) {
1069 return ldb_module_oom(module);
1071 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1072 if (!vstring) {
1073 return ldb_module_oom(module);
1075 *el->values = data_blob_string_const(vstring);
1078 return LDB_SUCCESS;
1081 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1082 struct ldb_message *msg,
1083 const char *attr,
1084 const uint32_t *old_val,
1085 const uint32_t *new_val)
1087 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1088 (const int32_t *)old_val,
1089 (const int32_t *)new_val);
1092 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1093 struct ldb_message *msg,
1094 const char *attr,
1095 const int64_t *old_val,
1096 const int64_t *new_val)
1098 struct ldb_message_element *el;
1099 int ret;
1100 char *vstring;
1102 if (old_val) {
1103 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1104 if (ret != LDB_SUCCESS) {
1105 return ret;
1107 el->num_values = 1;
1108 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1109 if (!el->values) {
1110 return ldb_module_oom(module);
1112 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1113 if (!vstring) {
1114 return ldb_module_oom(module);
1116 *el->values = data_blob_string_const(vstring);
1119 if (new_val) {
1120 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1121 if (ret != LDB_SUCCESS) {
1122 return ret;
1124 el->num_values = 1;
1125 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1126 if (!el->values) {
1127 return ldb_module_oom(module);
1129 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1130 if (!vstring) {
1131 return ldb_module_oom(module);
1133 *el->values = data_blob_string_const(vstring);
1136 return LDB_SUCCESS;
1139 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1140 struct ldb_message *msg,
1141 const char *attr,
1142 const uint64_t *old_val,
1143 const uint64_t *new_val)
1145 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1146 (const int64_t *)old_val,
1147 (const int64_t *)new_val);
1151 update an int32 attribute safely via a constrained delete/add
1153 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1154 struct ldb_dn *dn,
1155 const char *attr,
1156 const int32_t *old_val,
1157 const int32_t *new_val,
1158 struct ldb_request *parent)
1160 struct ldb_message *msg;
1161 int ret;
1163 msg = ldb_msg_new(module);
1164 msg->dn = dn;
1166 ret = dsdb_msg_constrainted_update_int32(module,
1167 msg, attr,
1168 old_val,
1169 new_val);
1170 if (ret != LDB_SUCCESS) {
1171 talloc_free(msg);
1172 return ret;
1175 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1176 talloc_free(msg);
1177 return ret;
1180 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1181 struct ldb_dn *dn,
1182 const char *attr,
1183 const uint32_t *old_val,
1184 const uint32_t *new_val,
1185 struct ldb_request *parent)
1187 return dsdb_module_constrainted_update_int32(module, dn, attr,
1188 (const int32_t *)old_val,
1189 (const int32_t *)new_val, parent);
1193 update an int64 attribute safely via a constrained delete/add
1195 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1196 struct ldb_dn *dn,
1197 const char *attr,
1198 const int64_t *old_val,
1199 const int64_t *new_val,
1200 struct ldb_request *parent)
1202 struct ldb_message *msg;
1203 int ret;
1205 msg = ldb_msg_new(module);
1206 msg->dn = dn;
1208 ret = dsdb_msg_constrainted_update_int64(module,
1209 msg, attr,
1210 old_val,
1211 new_val);
1212 if (ret != LDB_SUCCESS) {
1213 talloc_free(msg);
1214 return ret;
1217 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1218 talloc_free(msg);
1219 return ret;
1222 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1223 struct ldb_dn *dn,
1224 const char *attr,
1225 const uint64_t *old_val,
1226 const uint64_t *new_val,
1227 struct ldb_request *parent)
1229 return dsdb_module_constrainted_update_int64(module, dn, attr,
1230 (const int64_t *)old_val,
1231 (const int64_t *)new_val,
1232 parent);
1236 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1237 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1239 int ret;
1240 struct ldb_dn *new_dn;
1241 struct ldb_context *ldb = ldb_module_get_ctx(module);
1242 static const char *attrs[] = { "dSHeuristics", NULL };
1243 struct ldb_result *res;
1245 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1246 if (!ldb_dn_add_child_fmt(new_dn,
1247 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1248 talloc_free(new_dn);
1249 return NULL;
1251 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1252 new_dn,
1253 attrs,
1254 DSDB_FLAG_NEXT_MODULE,
1255 parent);
1256 if (ret == LDB_SUCCESS && res->count == 1) {
1257 talloc_free(new_dn);
1258 return ldb_msg_find_ldb_val(res->msgs[0],
1259 "dSHeuristics");
1261 talloc_free(new_dn);
1262 return NULL;
1265 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1267 TALLOC_CTX *tmp_ctx = talloc_new(module);
1268 bool result;
1269 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1270 tmp_ctx, parent);
1271 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1272 result = true;
1273 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1274 result = false;
1275 } else {
1276 result = true;
1279 talloc_free(tmp_ctx);
1280 return result;
1283 bool dsdb_user_password_support(struct ldb_module *module,
1284 TALLOC_CTX *mem_ctx,
1285 struct ldb_request *parent)
1287 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1288 bool result;
1289 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1290 tmp_ctx,
1291 parent);
1292 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1293 result = false;
1294 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1295 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1296 result = false;
1297 } else {
1298 result = true;
1301 talloc_free(tmp_ctx);
1302 return result;
1306 show the chain of requests, useful for debugging async requests
1308 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1310 char *s = ldb_module_call_chain(req, req);
1311 DEBUG(level, ("%s\n", s));
1312 talloc_free(s);
1316 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1317 * performing a modify operation.
1319 * In order that the constraint checking by the "objectclass_attrs" LDB module
1320 * does work properly, the change request should remain similar or only be
1321 * enhanced (no other modifications as deletions, variations).
1323 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1324 const char *attr_name,
1325 enum ldb_request_type operation)
1327 struct ldb_message_element *el = NULL;
1328 unsigned int i;
1330 /* We've to walk over all modification entries and consider the last
1331 * non-delete one which belongs to "attr_name".
1333 * If "el" is NULL afterwards then that means there was no interesting
1334 * change entry. */
1335 for (i = 0; i < msg->num_elements; i++) {
1336 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1337 if ((operation == LDB_MODIFY) &&
1338 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1339 == LDB_FLAG_MOD_DELETE)) {
1340 continue;
1342 el = &msg->elements[i];
1346 return el;