s3-pylibsmb: Factor out py_tevent_cond_wait
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / util.c
blob253d5c1d2ccbac123e71ebc55e38dc53c02af3ce
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 tmp_ctx = talloc_new(ldb);
696 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
697 if (feature_dn == NULL) {
698 talloc_free(tmp_ctx);
699 return ldb_operr(ldb_module_get_ctx(module));
702 *feature_enabled = false;
704 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
705 if (ret != LDB_SUCCESS) {
706 ldb_asprintf_errstring(ldb,
707 "Could not find the feature object - dn: %s\n",
708 ldb_dn_get_linearized(feature_dn));
709 talloc_free(tmp_ctx);
710 return LDB_ERR_OPERATIONS_ERROR;
712 if (res->msgs[0]->num_elements > 0) {
713 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
715 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
717 for (i=0; i<el->num_values; i++) {
718 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
720 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
721 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
722 if (ret != LDB_SUCCESS) {
723 ldb_asprintf_errstring(ldb,
724 "Could no find object dn: %s\n",
725 ldb_dn_get_linearized(search_dn));
726 talloc_free(tmp_ctx);
727 return LDB_ERR_OPERATIONS_ERROR;
730 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
732 if (GUID_compare(&search_guid, &op_feature_guid) == 0) {
733 *feature_enabled = true;
734 break;
738 talloc_free(tmp_ctx);
739 return LDB_SUCCESS;
743 find the NTDS GUID from a computers DN record
745 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
746 TALLOC_CTX *mem_ctx,
747 struct ldb_dn *computer_dn,
748 struct GUID *ntds_guid,
749 struct ldb_request *parent)
751 int ret;
752 struct ldb_dn *dn;
754 *ntds_guid = GUID_zero();
756 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
757 "serverReferenceBL", &dn, parent);
758 if (ret != LDB_SUCCESS) {
759 return ret;
762 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
763 talloc_free(dn);
764 return LDB_ERR_OPERATIONS_ERROR;
767 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
768 talloc_free(dn);
769 return ret;
773 find a 'reference' DN that points at another object
774 (eg. serverReference, rIDManagerReference etc)
776 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
777 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
779 const char *attrs[2];
780 struct ldb_result *res;
781 int ret;
783 attrs[0] = attribute;
784 attrs[1] = NULL;
786 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
787 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
788 if (ret != LDB_SUCCESS) {
789 return ret;
792 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
793 mem_ctx, res->msgs[0], attribute);
794 if (!*dn) {
795 ldb_reset_err_string(ldb_module_get_ctx(module));
796 talloc_free(res);
797 return LDB_ERR_NO_SUCH_ATTRIBUTE;
800 talloc_free(res);
801 return LDB_SUCCESS;
805 find the RID Manager$ DN via the rIDManagerReference attribute in the
806 base DN
808 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
809 struct ldb_request *parent)
811 return dsdb_module_reference_dn(module, mem_ctx,
812 ldb_get_default_basedn(ldb_module_get_ctx(module)),
813 "rIDManagerReference", dn, parent);
817 used to chain to the callers callback
819 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
821 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
823 talloc_steal(up_req, req);
824 return up_req->callback(up_req, ares);
828 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
829 object for a partition
831 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
832 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
834 struct ldb_context *ldb = ldb_module_get_ctx(module);
835 struct ldb_request *req;
836 int ret;
837 TALLOC_CTX *tmp_ctx = talloc_new(module);
838 struct dsdb_control_current_partition *p_ctrl;
839 struct ldb_result *res;
841 res = talloc_zero(tmp_ctx, struct ldb_result);
842 if (!res) {
843 talloc_free(tmp_ctx);
844 return ldb_module_oom(module);
847 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
848 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
849 LDB_SCOPE_BASE,
850 NULL, NULL,
851 NULL,
852 res, ldb_search_default_callback,
853 parent);
854 LDB_REQ_SET_LOCATION(req);
855 if (ret != LDB_SUCCESS) {
856 talloc_free(tmp_ctx);
857 return ret;
860 p_ctrl = talloc(req, struct dsdb_control_current_partition);
861 if (p_ctrl == NULL) {
862 talloc_free(tmp_ctx);
863 return ldb_module_oom(module);
865 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
866 p_ctrl->dn = dn;
869 ret = ldb_request_add_control(req,
870 DSDB_CONTROL_CURRENT_PARTITION_OID,
871 false, p_ctrl);
872 if (ret != LDB_SUCCESS) {
873 talloc_free(tmp_ctx);
874 return ret;
877 /* Run the new request */
878 ret = ldb_next_request(module, req);
880 if (ret == LDB_SUCCESS) {
881 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
884 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
885 /* it hasn't been created yet, which means
886 an implicit value of zero */
887 *uSN = 0;
888 talloc_free(tmp_ctx);
889 ldb_reset_err_string(ldb);
890 return LDB_SUCCESS;
893 if (ret != LDB_SUCCESS) {
894 talloc_free(tmp_ctx);
895 return ret;
898 if (res->count != 1) {
899 *uSN = 0;
900 if (urgent_uSN) {
901 *urgent_uSN = 0;
903 } else {
904 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
905 if (urgent_uSN) {
906 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
910 talloc_free(tmp_ctx);
912 return LDB_SUCCESS;
916 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
917 partition
919 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
920 uint64_t uSN, uint64_t urgent_uSN,
921 struct ldb_request *parent)
923 struct ldb_context *ldb = ldb_module_get_ctx(module);
924 struct ldb_request *req;
925 struct ldb_message *msg;
926 struct dsdb_control_current_partition *p_ctrl;
927 int ret;
928 struct ldb_result *res;
930 msg = ldb_msg_new(module);
931 if (msg == NULL) {
932 return ldb_module_oom(module);
935 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
936 if (msg->dn == NULL) {
937 talloc_free(msg);
938 return ldb_operr(ldb_module_get_ctx(module));
941 res = talloc_zero(msg, struct ldb_result);
942 if (!res) {
943 talloc_free(msg);
944 return ldb_module_oom(module);
947 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
948 if (ret != LDB_SUCCESS) {
949 talloc_free(msg);
950 return ret;
952 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
954 /* urgent_uSN is optional so may not be stored */
955 if (urgent_uSN) {
956 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
957 urgent_uSN);
958 if (ret != LDB_SUCCESS) {
959 talloc_free(msg);
960 return ret;
962 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
966 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
967 if (p_ctrl == NULL) {
968 talloc_free(msg);
969 return ldb_oom(ldb);
971 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
972 p_ctrl->dn = dn;
973 ret = ldb_build_mod_req(&req, ldb, msg,
974 msg,
975 NULL,
976 res,
977 ldb_modify_default_callback,
978 parent);
979 LDB_REQ_SET_LOCATION(req);
980 again:
981 if (ret != LDB_SUCCESS) {
982 talloc_free(msg);
983 return ret;
986 ret = ldb_request_add_control(req,
987 DSDB_CONTROL_CURRENT_PARTITION_OID,
988 false, p_ctrl);
989 if (ret != LDB_SUCCESS) {
990 talloc_free(msg);
991 return ret;
994 /* Run the new request */
995 ret = ldb_next_request(module, req);
997 if (ret == LDB_SUCCESS) {
998 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1000 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1001 ret = ldb_build_add_req(&req, ldb, msg,
1002 msg,
1003 NULL,
1004 res,
1005 ldb_modify_default_callback,
1006 parent);
1007 LDB_REQ_SET_LOCATION(req);
1008 goto again;
1011 talloc_free(msg);
1013 return ret;
1016 bool dsdb_module_am_system(struct ldb_module *module)
1018 struct ldb_context *ldb = ldb_module_get_ctx(module);
1019 struct auth_session_info *session_info
1020 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1021 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1024 bool dsdb_module_am_administrator(struct ldb_module *module)
1026 struct ldb_context *ldb = ldb_module_get_ctx(module);
1027 struct auth_session_info *session_info
1028 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1029 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1033 check if the recyclebin is enabled
1035 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1037 struct ldb_context *ldb = ldb_module_get_ctx(module);
1038 struct GUID recyclebin_guid;
1039 int ret;
1041 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1043 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1044 if (ret != LDB_SUCCESS) {
1045 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1046 return LDB_ERR_UNWILLING_TO_PERFORM;
1049 return LDB_SUCCESS;
1052 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1053 struct ldb_message *msg,
1054 const char *attr,
1055 const int32_t *old_val,
1056 const int32_t *new_val)
1058 struct ldb_message_element *el;
1059 int ret;
1060 char *vstring;
1062 if (old_val) {
1063 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1064 if (ret != LDB_SUCCESS) {
1065 return ret;
1067 el->num_values = 1;
1068 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1069 if (!el->values) {
1070 return ldb_module_oom(module);
1072 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1073 if (!vstring) {
1074 return ldb_module_oom(module);
1076 *el->values = data_blob_string_const(vstring);
1079 if (new_val) {
1080 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1081 if (ret != LDB_SUCCESS) {
1082 return ret;
1084 el->num_values = 1;
1085 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1086 if (!el->values) {
1087 return ldb_module_oom(module);
1089 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1090 if (!vstring) {
1091 return ldb_module_oom(module);
1093 *el->values = data_blob_string_const(vstring);
1096 return LDB_SUCCESS;
1099 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1100 struct ldb_message *msg,
1101 const char *attr,
1102 const uint32_t *old_val,
1103 const uint32_t *new_val)
1105 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1106 (const int32_t *)old_val,
1107 (const int32_t *)new_val);
1110 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1111 struct ldb_message *msg,
1112 const char *attr,
1113 const int64_t *old_val,
1114 const int64_t *new_val)
1116 struct ldb_message_element *el;
1117 int ret;
1118 char *vstring;
1120 if (old_val) {
1121 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1122 if (ret != LDB_SUCCESS) {
1123 return ret;
1125 el->num_values = 1;
1126 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1127 if (!el->values) {
1128 return ldb_module_oom(module);
1130 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1131 if (!vstring) {
1132 return ldb_module_oom(module);
1134 *el->values = data_blob_string_const(vstring);
1137 if (new_val) {
1138 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1139 if (ret != LDB_SUCCESS) {
1140 return ret;
1142 el->num_values = 1;
1143 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1144 if (!el->values) {
1145 return ldb_module_oom(module);
1147 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1148 if (!vstring) {
1149 return ldb_module_oom(module);
1151 *el->values = data_blob_string_const(vstring);
1154 return LDB_SUCCESS;
1157 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1158 struct ldb_message *msg,
1159 const char *attr,
1160 const uint64_t *old_val,
1161 const uint64_t *new_val)
1163 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1164 (const int64_t *)old_val,
1165 (const int64_t *)new_val);
1169 update an int32 attribute safely via a constrained delete/add
1171 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1172 struct ldb_dn *dn,
1173 const char *attr,
1174 const int32_t *old_val,
1175 const int32_t *new_val,
1176 struct ldb_request *parent)
1178 struct ldb_message *msg;
1179 int ret;
1181 msg = ldb_msg_new(module);
1182 msg->dn = dn;
1184 ret = dsdb_msg_constrainted_update_int32(module,
1185 msg, attr,
1186 old_val,
1187 new_val);
1188 if (ret != LDB_SUCCESS) {
1189 talloc_free(msg);
1190 return ret;
1193 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1194 talloc_free(msg);
1195 return ret;
1198 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1199 struct ldb_dn *dn,
1200 const char *attr,
1201 const uint32_t *old_val,
1202 const uint32_t *new_val,
1203 struct ldb_request *parent)
1205 return dsdb_module_constrainted_update_int32(module, dn, attr,
1206 (const int32_t *)old_val,
1207 (const int32_t *)new_val, parent);
1211 update an int64 attribute safely via a constrained delete/add
1213 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1214 struct ldb_dn *dn,
1215 const char *attr,
1216 const int64_t *old_val,
1217 const int64_t *new_val,
1218 struct ldb_request *parent)
1220 struct ldb_message *msg;
1221 int ret;
1223 msg = ldb_msg_new(module);
1224 msg->dn = dn;
1226 ret = dsdb_msg_constrainted_update_int64(module,
1227 msg, attr,
1228 old_val,
1229 new_val);
1230 if (ret != LDB_SUCCESS) {
1231 talloc_free(msg);
1232 return ret;
1235 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1236 talloc_free(msg);
1237 return ret;
1240 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1241 struct ldb_dn *dn,
1242 const char *attr,
1243 const uint64_t *old_val,
1244 const uint64_t *new_val,
1245 struct ldb_request *parent)
1247 return dsdb_module_constrainted_update_int64(module, dn, attr,
1248 (const int64_t *)old_val,
1249 (const int64_t *)new_val,
1250 parent);
1254 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1255 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1257 int ret;
1258 struct ldb_dn *new_dn;
1259 struct ldb_context *ldb = ldb_module_get_ctx(module);
1260 static const char *attrs[] = { "dSHeuristics", NULL };
1261 struct ldb_result *res;
1263 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1264 if (!ldb_dn_add_child_fmt(new_dn,
1265 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1266 talloc_free(new_dn);
1267 return NULL;
1269 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1270 new_dn,
1271 attrs,
1272 DSDB_FLAG_NEXT_MODULE,
1273 parent);
1274 if (ret == LDB_SUCCESS && res->count == 1) {
1275 talloc_free(new_dn);
1276 return ldb_msg_find_ldb_val(res->msgs[0],
1277 "dSHeuristics");
1279 talloc_free(new_dn);
1280 return NULL;
1283 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1285 TALLOC_CTX *tmp_ctx = talloc_new(module);
1286 bool result;
1287 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1288 tmp_ctx, parent);
1289 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1290 result = true;
1291 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1292 result = false;
1293 } else {
1294 result = true;
1297 talloc_free(tmp_ctx);
1298 return result;
1301 bool dsdb_user_password_support(struct ldb_module *module,
1302 TALLOC_CTX *mem_ctx,
1303 struct ldb_request *parent)
1305 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1306 bool result;
1307 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1308 tmp_ctx,
1309 parent);
1310 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1311 result = false;
1312 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1313 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1314 result = false;
1315 } else {
1316 result = true;
1319 talloc_free(tmp_ctx);
1320 return result;
1324 show the chain of requests, useful for debugging async requests
1326 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1328 char *s = ldb_module_call_chain(req, req);
1329 DEBUG(level, ("%s\n", s));
1330 talloc_free(s);
1334 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1335 * performing a modify operation.
1337 * In order that the constraint checking by the "objectclass_attrs" LDB module
1338 * does work properly, the change request should remain similar or only be
1339 * enhanced (no other modifications as deletions, variations).
1341 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1342 const char *attr_name,
1343 enum ldb_request_type operation)
1345 struct ldb_message_element *el = NULL;
1346 unsigned int i;
1348 /* We've to walk over all modification entries and consider the last
1349 * non-delete one which belongs to "attr_name".
1351 * If "el" is NULL afterwards then that means there was no interesting
1352 * change entry. */
1353 for (i = 0; i < msg->num_elements; i++) {
1354 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1355 if ((operation == LDB_MODIFY) &&
1356 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1357 == LDB_FLAG_MOD_DELETE)) {
1358 continue;
1360 el = &msg->elements[i];
1364 return el;
1368 * This function determines the (last) structural or 88 object class of a passed
1369 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1370 * Without schema this does not work and hence NULL is returned.
1372 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1373 const struct ldb_message_element *element)
1375 const struct dsdb_class *last_class;
1377 if (schema == NULL) {
1378 return NULL;
1381 if (element->num_values == 0) {
1382 return NULL;
1385 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1386 &element->values[element->num_values-1]);
1387 if (last_class == NULL) {
1388 return NULL;
1390 if (last_class->objectClassCategory > 1) {
1391 return NULL;
1394 return last_class;