s3:registry: do not use regdb functions during db upgrade
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / util.c
blob4e0001d17bc09e429e98fca5b00cd70037135352
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;
320 a ldb_extended request operating on modules below the
321 current module
323 Note that this does not automatically start a transaction. If you
324 need a transaction the caller needs to start it as needed.
326 int dsdb_module_extended(struct ldb_module *module,
327 TALLOC_CTX *mem_ctx,
328 struct ldb_result **_res,
329 const char* oid, void* data,
330 uint32_t dsdb_flags,
331 struct ldb_request *parent)
333 struct ldb_request *req;
334 int ret;
335 struct ldb_context *ldb = ldb_module_get_ctx(module);
336 TALLOC_CTX *tmp_ctx = talloc_new(module);
337 struct ldb_result *res;
339 if (_res != NULL) {
340 (*_res) = NULL;
343 res = talloc_zero(tmp_ctx, struct ldb_result);
344 if (!res) {
345 talloc_free(tmp_ctx);
346 return ldb_oom(ldb_module_get_ctx(module));
349 ret = ldb_build_extended_req(&req, ldb,
350 tmp_ctx,
351 oid,
352 data,
353 NULL,
354 res, ldb_extended_default_callback,
355 parent);
357 LDB_REQ_SET_LOCATION(req);
358 if (ret != LDB_SUCCESS) {
359 talloc_free(tmp_ctx);
360 return ret;
363 ret = dsdb_request_add_controls(req, dsdb_flags);
364 if (ret != LDB_SUCCESS) {
365 talloc_free(tmp_ctx);
366 return ret;
369 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
370 ldb_req_mark_trusted(req);
373 /* Run the new request */
374 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
375 ret = ldb_next_request(module, req);
376 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
377 ret = ldb_request(ldb_module_get_ctx(module), req);
378 } else {
379 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
380 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
381 ret = ops->extended(module, req);
383 if (ret == LDB_SUCCESS) {
384 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
387 if (_res != NULL && ret == LDB_SUCCESS) {
388 (*_res) = talloc_steal(mem_ctx, res);
391 talloc_free(tmp_ctx);
392 return ret;
397 a ldb_modify request operating on modules below the
398 current module
400 int dsdb_module_modify(struct ldb_module *module,
401 const struct ldb_message *message,
402 uint32_t dsdb_flags,
403 struct ldb_request *parent)
405 struct ldb_request *mod_req;
406 int ret;
407 struct ldb_context *ldb = ldb_module_get_ctx(module);
408 TALLOC_CTX *tmp_ctx = talloc_new(module);
409 struct ldb_result *res;
411 res = talloc_zero(tmp_ctx, struct ldb_result);
412 if (!res) {
413 talloc_free(tmp_ctx);
414 return ldb_oom(ldb_module_get_ctx(module));
417 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
418 message,
419 NULL,
420 res,
421 ldb_modify_default_callback,
422 parent);
423 LDB_REQ_SET_LOCATION(mod_req);
424 if (ret != LDB_SUCCESS) {
425 talloc_free(tmp_ctx);
426 return ret;
429 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
430 if (ret != LDB_SUCCESS) {
431 talloc_free(tmp_ctx);
432 return ret;
435 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
436 ldb_req_mark_trusted(mod_req);
439 /* Run the new request */
440 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
441 ret = ldb_next_request(module, mod_req);
442 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
443 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
444 } else {
445 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
446 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
447 ret = ops->modify(module, mod_req);
449 if (ret == LDB_SUCCESS) {
450 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
453 talloc_free(tmp_ctx);
454 return ret;
460 a ldb_rename request operating on modules below the
461 current module
463 int dsdb_module_rename(struct ldb_module *module,
464 struct ldb_dn *olddn, struct ldb_dn *newdn,
465 uint32_t dsdb_flags,
466 struct ldb_request *parent)
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;
474 res = talloc_zero(tmp_ctx, struct ldb_result);
475 if (!res) {
476 talloc_free(tmp_ctx);
477 return ldb_oom(ldb_module_get_ctx(module));
480 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
481 olddn,
482 newdn,
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;
493 ret = dsdb_request_add_controls(req, dsdb_flags);
494 if (ret != LDB_SUCCESS) {
495 talloc_free(tmp_ctx);
496 return ret;
499 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
500 ldb_req_mark_trusted(req);
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->rename(module, req);
513 if (ret == LDB_SUCCESS) {
514 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
517 talloc_free(tmp_ctx);
518 return ret;
522 a ldb_add request operating on modules below the
523 current module
525 int dsdb_module_add(struct ldb_module *module,
526 const struct ldb_message *message,
527 uint32_t dsdb_flags,
528 struct ldb_request *parent)
530 struct ldb_request *req;
531 int ret;
532 struct ldb_context *ldb = ldb_module_get_ctx(module);
533 TALLOC_CTX *tmp_ctx = talloc_new(module);
534 struct ldb_result *res;
536 res = talloc_zero(tmp_ctx, struct ldb_result);
537 if (!res) {
538 talloc_free(tmp_ctx);
539 return ldb_oom(ldb_module_get_ctx(module));
542 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
543 message,
544 NULL,
545 res,
546 ldb_modify_default_callback,
547 parent);
548 LDB_REQ_SET_LOCATION(req);
549 if (ret != LDB_SUCCESS) {
550 talloc_free(tmp_ctx);
551 return ret;
554 ret = dsdb_request_add_controls(req, dsdb_flags);
555 if (ret != LDB_SUCCESS) {
556 talloc_free(tmp_ctx);
557 return ret;
560 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
561 ldb_req_mark_trusted(req);
564 /* Run the new request */
565 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
566 ret = ldb_next_request(module, req);
567 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
568 ret = ldb_request(ldb_module_get_ctx(module), req);
569 } else {
570 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
571 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
572 ret = ops->add(module, req);
574 if (ret == LDB_SUCCESS) {
575 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
578 talloc_free(tmp_ctx);
579 return ret;
583 a ldb_delete request operating on modules below the
584 current module
586 int dsdb_module_del(struct ldb_module *module,
587 struct ldb_dn *dn,
588 uint32_t dsdb_flags,
589 struct ldb_request *parent)
591 struct ldb_request *req;
592 int ret;
593 struct ldb_context *ldb = ldb_module_get_ctx(module);
594 TALLOC_CTX *tmp_ctx = talloc_new(module);
595 struct ldb_result *res;
597 res = talloc_zero(tmp_ctx, struct ldb_result);
598 if (!res) {
599 talloc_free(tmp_ctx);
600 return ldb_oom(ldb);
603 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
605 NULL,
606 res,
607 ldb_modify_default_callback,
608 parent);
609 LDB_REQ_SET_LOCATION(req);
610 if (ret != LDB_SUCCESS) {
611 talloc_free(tmp_ctx);
612 return ret;
615 ret = dsdb_request_add_controls(req, dsdb_flags);
616 if (ret != LDB_SUCCESS) {
617 talloc_free(tmp_ctx);
618 return ret;
621 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
622 ldb_req_mark_trusted(req);
625 /* Run the new request */
626 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
627 ret = ldb_next_request(module, req);
628 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
629 ret = ldb_request(ldb_module_get_ctx(module), req);
630 } else {
631 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
632 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
633 ret = ops->del(module, req);
635 if (ret == LDB_SUCCESS) {
636 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
639 talloc_free(tmp_ctx);
640 return ret;
644 check if a single valued link has multiple non-deleted values
646 This is needed when we will be using the RELAX control to stop
647 ldb_tdb from checking single valued links
649 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
650 const struct ldb_message_element *el)
652 bool found_active = false;
653 unsigned int i;
655 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
656 el->num_values < 2) {
657 return LDB_SUCCESS;
660 for (i=0; i<el->num_values; i++) {
661 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
662 if (found_active) {
663 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
665 found_active = true;
669 return LDB_SUCCESS;
673 check if an optional feature is enabled on our own NTDS DN
675 Note that features can be marked as enabled in more than one
676 place. For example, the recyclebin feature is marked as enabled both
677 on the CN=Partitions,CN=Configurration object and on the NTDS DN of
678 each DC in the forest. It seems likely that it is the job of the KCC
679 to propogate between the two
681 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
683 TALLOC_CTX *tmp_ctx;
684 struct ldb_context *ldb = ldb_module_get_ctx(module);
685 struct ldb_result *res;
686 struct ldb_dn *search_dn;
687 struct GUID search_guid;
688 const char *attrs[] = {"msDS-EnabledFeature", NULL};
689 int ret;
690 unsigned int i;
691 struct ldb_message_element *el;
692 struct ldb_dn *feature_dn;
694 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module));
695 if (feature_dn == NULL) {
696 return ldb_operr(ldb_module_get_ctx(module));
699 *feature_enabled = false;
701 tmp_ctx = talloc_new(ldb);
703 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
704 if (ret != LDB_SUCCESS) {
705 ldb_asprintf_errstring(ldb,
706 "Could not find the feature object - dn: %s\n",
707 ldb_dn_get_linearized(feature_dn));
708 talloc_free(tmp_ctx);
709 return LDB_ERR_OPERATIONS_ERROR;
711 if (res->msgs[0]->num_elements > 0) {
712 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
714 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
716 for (i=0; i<el->num_values; i++) {
717 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
719 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
720 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
721 if (ret != LDB_SUCCESS) {
722 ldb_asprintf_errstring(ldb,
723 "Could no find object dn: %s\n",
724 ldb_dn_get_linearized(search_dn));
725 talloc_free(tmp_ctx);
726 return LDB_ERR_OPERATIONS_ERROR;
729 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
731 if (GUID_compare(&search_guid, &op_feature_guid) == 0) {
732 *feature_enabled = true;
733 break;
737 talloc_free(tmp_ctx);
738 return LDB_SUCCESS;
742 find the NTDS GUID from a computers DN record
744 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
745 TALLOC_CTX *mem_ctx,
746 struct ldb_dn *computer_dn,
747 struct GUID *ntds_guid,
748 struct ldb_request *parent)
750 int ret;
751 struct ldb_dn *dn;
753 *ntds_guid = GUID_zero();
755 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
756 "serverReferenceBL", &dn, parent);
757 if (ret != LDB_SUCCESS) {
758 return ret;
761 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
762 talloc_free(dn);
763 return LDB_ERR_OPERATIONS_ERROR;
766 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
767 talloc_free(dn);
768 return ret;
772 find a 'reference' DN that points at another object
773 (eg. serverReference, rIDManagerReference etc)
775 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
776 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
778 const char *attrs[2];
779 struct ldb_result *res;
780 int ret;
782 attrs[0] = attribute;
783 attrs[1] = NULL;
785 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
786 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
787 if (ret != LDB_SUCCESS) {
788 return ret;
791 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
792 mem_ctx, res->msgs[0], attribute);
793 if (!*dn) {
794 ldb_reset_err_string(ldb_module_get_ctx(module));
795 talloc_free(res);
796 return LDB_ERR_NO_SUCH_ATTRIBUTE;
799 talloc_free(res);
800 return LDB_SUCCESS;
804 find the RID Manager$ DN via the rIDManagerReference attribute in the
805 base DN
807 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
808 struct ldb_request *parent)
810 return dsdb_module_reference_dn(module, mem_ctx,
811 ldb_get_default_basedn(ldb_module_get_ctx(module)),
812 "rIDManagerReference", dn, parent);
816 used to chain to the callers callback
818 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
820 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
822 talloc_steal(up_req, req);
823 return up_req->callback(up_req, ares);
827 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
828 object for a partition
830 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
831 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
833 struct ldb_context *ldb = ldb_module_get_ctx(module);
834 struct ldb_request *req;
835 int ret;
836 TALLOC_CTX *tmp_ctx = talloc_new(module);
837 struct dsdb_control_current_partition *p_ctrl;
838 struct ldb_result *res;
840 res = talloc_zero(tmp_ctx, struct ldb_result);
841 if (!res) {
842 talloc_free(tmp_ctx);
843 return ldb_module_oom(module);
846 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
847 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
848 LDB_SCOPE_BASE,
849 NULL, NULL,
850 NULL,
851 res, ldb_search_default_callback,
852 parent);
853 LDB_REQ_SET_LOCATION(req);
854 if (ret != LDB_SUCCESS) {
855 talloc_free(tmp_ctx);
856 return ret;
859 p_ctrl = talloc(req, struct dsdb_control_current_partition);
860 if (p_ctrl == NULL) {
861 talloc_free(tmp_ctx);
862 return ldb_module_oom(module);
864 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
865 p_ctrl->dn = dn;
868 ret = ldb_request_add_control(req,
869 DSDB_CONTROL_CURRENT_PARTITION_OID,
870 false, p_ctrl);
871 if (ret != LDB_SUCCESS) {
872 talloc_free(tmp_ctx);
873 return ret;
876 /* Run the new request */
877 ret = ldb_next_request(module, req);
879 if (ret == LDB_SUCCESS) {
880 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
883 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
884 /* it hasn't been created yet, which means
885 an implicit value of zero */
886 *uSN = 0;
887 talloc_free(tmp_ctx);
888 ldb_reset_err_string(ldb);
889 return LDB_SUCCESS;
892 if (ret != LDB_SUCCESS) {
893 talloc_free(tmp_ctx);
894 return ret;
897 if (res->count != 1) {
898 *uSN = 0;
899 if (urgent_uSN) {
900 *urgent_uSN = 0;
902 } else {
903 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
904 if (urgent_uSN) {
905 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
909 talloc_free(tmp_ctx);
911 return LDB_SUCCESS;
915 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
916 partition
918 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
919 uint64_t uSN, uint64_t urgent_uSN,
920 struct ldb_request *parent)
922 struct ldb_context *ldb = ldb_module_get_ctx(module);
923 struct ldb_request *req;
924 struct ldb_message *msg;
925 struct dsdb_control_current_partition *p_ctrl;
926 int ret;
927 struct ldb_result *res;
929 msg = ldb_msg_new(module);
930 if (msg == NULL) {
931 return ldb_module_oom(module);
934 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
935 if (msg->dn == NULL) {
936 talloc_free(msg);
937 return ldb_operr(ldb_module_get_ctx(module));
940 res = talloc_zero(msg, struct ldb_result);
941 if (!res) {
942 talloc_free(msg);
943 return ldb_module_oom(module);
946 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
947 if (ret != LDB_SUCCESS) {
948 talloc_free(msg);
949 return ret;
951 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
953 /* urgent_uSN is optional so may not be stored */
954 if (urgent_uSN) {
955 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
956 urgent_uSN);
957 if (ret != LDB_SUCCESS) {
958 talloc_free(msg);
959 return ret;
961 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
965 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
966 if (p_ctrl == NULL) {
967 talloc_free(msg);
968 return ldb_oom(ldb);
970 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
971 p_ctrl->dn = dn;
972 ret = ldb_build_mod_req(&req, ldb, msg,
973 msg,
974 NULL,
975 res,
976 ldb_modify_default_callback,
977 parent);
978 LDB_REQ_SET_LOCATION(req);
979 again:
980 if (ret != LDB_SUCCESS) {
981 talloc_free(msg);
982 return ret;
985 ret = ldb_request_add_control(req,
986 DSDB_CONTROL_CURRENT_PARTITION_OID,
987 false, p_ctrl);
988 if (ret != LDB_SUCCESS) {
989 talloc_free(msg);
990 return ret;
993 /* Run the new request */
994 ret = ldb_next_request(module, req);
996 if (ret == LDB_SUCCESS) {
997 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
999 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1000 ret = ldb_build_add_req(&req, ldb, msg,
1001 msg,
1002 NULL,
1003 res,
1004 ldb_modify_default_callback,
1005 parent);
1006 LDB_REQ_SET_LOCATION(req);
1007 goto again;
1010 talloc_free(msg);
1012 return ret;
1015 bool dsdb_module_am_system(struct ldb_module *module)
1017 struct ldb_context *ldb = ldb_module_get_ctx(module);
1018 struct auth_session_info *session_info
1019 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1020 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1023 bool dsdb_module_am_administrator(struct ldb_module *module)
1025 struct ldb_context *ldb = ldb_module_get_ctx(module);
1026 struct auth_session_info *session_info
1027 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1028 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1032 check if the recyclebin is enabled
1034 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1036 struct ldb_context *ldb = ldb_module_get_ctx(module);
1037 struct GUID recyclebin_guid;
1038 int ret;
1040 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1042 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1043 if (ret != LDB_SUCCESS) {
1044 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1045 return LDB_ERR_UNWILLING_TO_PERFORM;
1048 return LDB_SUCCESS;
1051 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1052 struct ldb_message *msg,
1053 const char *attr,
1054 const int32_t *old_val,
1055 const int32_t *new_val)
1057 struct ldb_message_element *el;
1058 int ret;
1059 char *vstring;
1061 if (old_val) {
1062 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &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)*old_val);
1072 if (!vstring) {
1073 return ldb_module_oom(module);
1075 *el->values = data_blob_string_const(vstring);
1078 if (new_val) {
1079 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1080 if (ret != LDB_SUCCESS) {
1081 return ret;
1083 el->num_values = 1;
1084 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1085 if (!el->values) {
1086 return ldb_module_oom(module);
1088 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1089 if (!vstring) {
1090 return ldb_module_oom(module);
1092 *el->values = data_blob_string_const(vstring);
1095 return LDB_SUCCESS;
1098 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1099 struct ldb_message *msg,
1100 const char *attr,
1101 const uint32_t *old_val,
1102 const uint32_t *new_val)
1104 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1105 (const int32_t *)old_val,
1106 (const int32_t *)new_val);
1109 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1110 struct ldb_message *msg,
1111 const char *attr,
1112 const int64_t *old_val,
1113 const int64_t *new_val)
1115 struct ldb_message_element *el;
1116 int ret;
1117 char *vstring;
1119 if (old_val) {
1120 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &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)*old_val);
1130 if (!vstring) {
1131 return ldb_module_oom(module);
1133 *el->values = data_blob_string_const(vstring);
1136 if (new_val) {
1137 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1138 if (ret != LDB_SUCCESS) {
1139 return ret;
1141 el->num_values = 1;
1142 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1143 if (!el->values) {
1144 return ldb_module_oom(module);
1146 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1147 if (!vstring) {
1148 return ldb_module_oom(module);
1150 *el->values = data_blob_string_const(vstring);
1153 return LDB_SUCCESS;
1156 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1157 struct ldb_message *msg,
1158 const char *attr,
1159 const uint64_t *old_val,
1160 const uint64_t *new_val)
1162 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1163 (const int64_t *)old_val,
1164 (const int64_t *)new_val);
1168 update an int32 attribute safely via a constrained delete/add
1170 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1171 struct ldb_dn *dn,
1172 const char *attr,
1173 const int32_t *old_val,
1174 const int32_t *new_val,
1175 struct ldb_request *parent)
1177 struct ldb_message *msg;
1178 int ret;
1180 msg = ldb_msg_new(module);
1181 msg->dn = dn;
1183 ret = dsdb_msg_constrainted_update_int32(module,
1184 msg, attr,
1185 old_val,
1186 new_val);
1187 if (ret != LDB_SUCCESS) {
1188 talloc_free(msg);
1189 return ret;
1192 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1193 talloc_free(msg);
1194 return ret;
1197 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1198 struct ldb_dn *dn,
1199 const char *attr,
1200 const uint32_t *old_val,
1201 const uint32_t *new_val,
1202 struct ldb_request *parent)
1204 return dsdb_module_constrainted_update_int32(module, dn, attr,
1205 (const int32_t *)old_val,
1206 (const int32_t *)new_val, parent);
1210 update an int64 attribute safely via a constrained delete/add
1212 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1213 struct ldb_dn *dn,
1214 const char *attr,
1215 const int64_t *old_val,
1216 const int64_t *new_val,
1217 struct ldb_request *parent)
1219 struct ldb_message *msg;
1220 int ret;
1222 msg = ldb_msg_new(module);
1223 msg->dn = dn;
1225 ret = dsdb_msg_constrainted_update_int64(module,
1226 msg, attr,
1227 old_val,
1228 new_val);
1229 if (ret != LDB_SUCCESS) {
1230 talloc_free(msg);
1231 return ret;
1234 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1235 talloc_free(msg);
1236 return ret;
1239 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1240 struct ldb_dn *dn,
1241 const char *attr,
1242 const uint64_t *old_val,
1243 const uint64_t *new_val,
1244 struct ldb_request *parent)
1246 return dsdb_module_constrainted_update_int64(module, dn, attr,
1247 (const int64_t *)old_val,
1248 (const int64_t *)new_val,
1249 parent);
1253 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1254 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1256 int ret;
1257 struct ldb_dn *new_dn;
1258 struct ldb_context *ldb = ldb_module_get_ctx(module);
1259 static const char *attrs[] = { "dSHeuristics", NULL };
1260 struct ldb_result *res;
1262 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1263 if (!ldb_dn_add_child_fmt(new_dn,
1264 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1265 talloc_free(new_dn);
1266 return NULL;
1268 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1269 new_dn,
1270 attrs,
1271 DSDB_FLAG_NEXT_MODULE,
1272 parent);
1273 if (ret == LDB_SUCCESS && res->count == 1) {
1274 talloc_free(new_dn);
1275 return ldb_msg_find_ldb_val(res->msgs[0],
1276 "dSHeuristics");
1278 talloc_free(new_dn);
1279 return NULL;
1282 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1284 TALLOC_CTX *tmp_ctx = talloc_new(module);
1285 bool result;
1286 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1287 tmp_ctx, parent);
1288 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1289 result = true;
1290 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1291 result = false;
1292 } else {
1293 result = true;
1296 talloc_free(tmp_ctx);
1297 return result;
1300 bool dsdb_user_password_support(struct ldb_module *module,
1301 TALLOC_CTX *mem_ctx,
1302 struct ldb_request *parent)
1304 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1305 bool result;
1306 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1307 tmp_ctx,
1308 parent);
1309 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1310 result = false;
1311 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1312 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1313 result = false;
1314 } else {
1315 result = true;
1318 talloc_free(tmp_ctx);
1319 return result;
1323 show the chain of requests, useful for debugging async requests
1325 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1327 char *s = ldb_module_call_chain(req, req);
1328 DEBUG(level, ("%s\n", s));
1329 talloc_free(s);
1333 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1334 * performing a modify operation.
1336 * In order that the constraint checking by the "objectclass_attrs" LDB module
1337 * does work properly, the change request should remain similar or only be
1338 * enhanced (no other modifications as deletions, variations).
1340 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1341 const char *attr_name,
1342 enum ldb_request_type operation)
1344 struct ldb_message_element *el = NULL;
1345 unsigned int i;
1347 /* We've to walk over all modification entries and consider the last
1348 * non-delete one which belongs to "attr_name".
1350 * If "el" is NULL afterwards then that means there was no interesting
1351 * change entry. */
1352 for (i = 0; i < msg->num_elements; i++) {
1353 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1354 if ((operation == LDB_MODIFY) &&
1355 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1356 == LDB_FLAG_MOD_DELETE)) {
1357 continue;
1359 el = &msg->elements[i];
1363 return el;