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/>.
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"
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,
37 struct ldb_result **_res,
38 struct ldb_dn *basedn,
39 const char * const *attrs,
41 struct ldb_request *parent)
44 struct ldb_request *req;
46 struct ldb_result *res;
48 tmp_ctx = talloc_new(mem_ctx);
50 res = talloc_zero(tmp_ctx, struct ldb_result);
53 return ldb_oom(ldb_module_get_ctx(module));
56 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
63 ldb_search_default_callback,
65 LDB_REQ_SET_LOCATION(req);
66 if (ret != LDB_SUCCESS) {
71 ret = dsdb_request_add_controls(req, dsdb_flags);
72 if (ret != LDB_SUCCESS) {
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);
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) {
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);
107 *_res = talloc_steal(mem_ctx, res);
109 talloc_free(tmp_ctx);
113 int dsdb_module_search_tree(struct ldb_module *module,
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,
121 struct ldb_request *parent)
124 struct ldb_request *req;
126 struct ldb_result *res;
128 tmp_ctx = talloc_new(mem_ctx);
131 res = talloc_zero(tmp_ctx, struct ldb_result);
133 talloc_free(tmp_ctx);
134 return ldb_oom(ldb_module_get_ctx(module));
137 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
144 ldb_search_default_callback,
146 LDB_REQ_SET_LOCATION(req);
147 if (ret != LDB_SUCCESS) {
148 talloc_free(tmp_ctx);
152 ret = dsdb_request_add_controls(req, dsdb_flags);
153 if (ret != LDB_SUCCESS) {
154 talloc_free(tmp_ctx);
158 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
159 ldb_req_mark_trusted(req);
162 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
163 ret = ldb_next_request(module, req);
164 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
165 ret = ldb_request(ldb_module_get_ctx(module), req);
167 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
168 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
169 ret = ops->search(module, req);
171 if (ret == LDB_SUCCESS) {
172 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
176 if (ret == LDB_SUCCESS) {
177 *_res = talloc_steal(mem_ctx, res);
179 talloc_free(tmp_ctx);
184 search for attrs in the modules below
186 int dsdb_module_search(struct ldb_module *module,
188 struct ldb_result **_res,
189 struct ldb_dn *basedn, enum ldb_scope scope,
190 const char * const *attrs,
192 struct ldb_request *parent,
193 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
199 struct ldb_parse_tree *tree;
201 tmp_ctx = talloc_new(mem_ctx);
204 va_start(ap, format);
205 expression = talloc_vasprintf(tmp_ctx, format, ap);
209 talloc_free(tmp_ctx);
210 return ldb_oom(ldb_module_get_ctx(module));
216 tree = ldb_parse_tree(tmp_ctx, expression);
218 talloc_free(tmp_ctx);
219 ldb_set_errstring(ldb_module_get_ctx(module),
220 "Unable to parse search expression");
221 return LDB_ERR_OPERATIONS_ERROR;
224 ret = dsdb_module_search_tree(module,
234 talloc_free(tmp_ctx);
239 find a DN given a GUID. This searches across all partitions
241 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
242 const struct GUID *guid, struct ldb_dn **dn,
243 struct ldb_request *parent)
245 struct ldb_result *res;
246 const char *attrs[] = { NULL };
247 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
250 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
252 DSDB_FLAG_NEXT_MODULE |
253 DSDB_SEARCH_SHOW_RECYCLED |
254 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
255 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
257 "objectGUID=%s", GUID_string(tmp_ctx, guid));
258 if (ret != LDB_SUCCESS) {
259 talloc_free(tmp_ctx);
262 if (res->count == 0) {
263 talloc_free(tmp_ctx);
264 return LDB_ERR_NO_SUCH_OBJECT;
266 if (res->count != 1) {
267 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
268 GUID_string(tmp_ctx, guid));
269 talloc_free(tmp_ctx);
270 return LDB_ERR_OPERATIONS_ERROR;
273 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
275 talloc_free(tmp_ctx);
280 find a GUID given a DN.
282 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
283 struct ldb_request *parent)
285 const char *attrs[] = { NULL };
286 struct ldb_result *res;
287 TALLOC_CTX *tmp_ctx = talloc_new(module);
291 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
292 DSDB_FLAG_NEXT_MODULE |
293 DSDB_SEARCH_SHOW_RECYCLED |
294 DSDB_SEARCH_SHOW_EXTENDED_DN,
296 if (ret != LDB_SUCCESS) {
297 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
298 ldb_dn_get_linearized(dn));
299 talloc_free(tmp_ctx);
303 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
304 if (!NT_STATUS_IS_OK(status)) {
305 talloc_free(tmp_ctx);
306 return ldb_operr(ldb_module_get_ctx(module));
309 talloc_free(tmp_ctx);
313 a ldb_extended request operating on modules below the
316 int dsdb_module_extended(struct ldb_module *module,
317 const char* oid, void* data,
319 struct ldb_request *parent)
321 struct ldb_request *req;
323 struct ldb_context *ldb = ldb_module_get_ctx(module);
324 TALLOC_CTX *tmp_ctx = talloc_new(module);
325 struct ldb_result *res;
327 res = talloc_zero(tmp_ctx, struct ldb_result);
329 talloc_free(tmp_ctx);
330 return ldb_oom(ldb_module_get_ctx(module));
333 ret = ldb_build_extended_req(&req, ldb,
338 res, ldb_extended_default_callback,
341 LDB_REQ_SET_LOCATION(req);
342 if (ret != LDB_SUCCESS) {
343 talloc_free(tmp_ctx);
347 ret = dsdb_request_add_controls(req, dsdb_flags);
348 if (ret != LDB_SUCCESS) {
349 talloc_free(tmp_ctx);
353 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
354 ldb_req_mark_trusted(req);
357 /* Run the new request */
358 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
359 ret = ldb_next_request(module, req);
360 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
361 ret = ldb_request(ldb_module_get_ctx(module), req);
363 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
364 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
365 ret = ops->extended(module, req);
367 if (ret == LDB_SUCCESS) {
368 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
371 talloc_free(tmp_ctx);
375 a ldb_modify request operating on modules below the
378 int dsdb_module_modify(struct ldb_module *module,
379 const struct ldb_message *message,
381 struct ldb_request *parent)
383 struct ldb_request *mod_req;
385 struct ldb_context *ldb = ldb_module_get_ctx(module);
386 TALLOC_CTX *tmp_ctx = talloc_new(module);
387 struct ldb_result *res;
389 res = talloc_zero(tmp_ctx, struct ldb_result);
391 talloc_free(tmp_ctx);
392 return ldb_oom(ldb_module_get_ctx(module));
395 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
399 ldb_modify_default_callback,
401 LDB_REQ_SET_LOCATION(mod_req);
402 if (ret != LDB_SUCCESS) {
403 talloc_free(tmp_ctx);
407 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
408 if (ret != LDB_SUCCESS) {
409 talloc_free(tmp_ctx);
413 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
414 ldb_req_mark_trusted(mod_req);
417 /* Run the new request */
418 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
419 ret = ldb_next_request(module, mod_req);
420 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
421 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
423 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
424 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
425 ret = ops->modify(module, mod_req);
427 if (ret == LDB_SUCCESS) {
428 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
431 talloc_free(tmp_ctx);
438 a ldb_rename request operating on modules below the
441 int dsdb_module_rename(struct ldb_module *module,
442 struct ldb_dn *olddn, struct ldb_dn *newdn,
444 struct ldb_request *parent)
446 struct ldb_request *req;
448 struct ldb_context *ldb = ldb_module_get_ctx(module);
449 TALLOC_CTX *tmp_ctx = talloc_new(module);
450 struct ldb_result *res;
452 res = talloc_zero(tmp_ctx, struct ldb_result);
454 talloc_free(tmp_ctx);
455 return ldb_oom(ldb_module_get_ctx(module));
458 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
463 ldb_modify_default_callback,
465 LDB_REQ_SET_LOCATION(req);
466 if (ret != LDB_SUCCESS) {
467 talloc_free(tmp_ctx);
471 ret = dsdb_request_add_controls(req, dsdb_flags);
472 if (ret != LDB_SUCCESS) {
473 talloc_free(tmp_ctx);
477 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
478 ldb_req_mark_trusted(req);
481 /* Run the new request */
482 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
483 ret = ldb_next_request(module, req);
484 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
485 ret = ldb_request(ldb_module_get_ctx(module), req);
487 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
488 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
489 ret = ops->rename(module, req);
491 if (ret == LDB_SUCCESS) {
492 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
495 talloc_free(tmp_ctx);
500 a ldb_add request operating on modules below the
503 int dsdb_module_add(struct ldb_module *module,
504 const struct ldb_message *message,
506 struct ldb_request *parent)
508 struct ldb_request *req;
510 struct ldb_context *ldb = ldb_module_get_ctx(module);
511 TALLOC_CTX *tmp_ctx = talloc_new(module);
512 struct ldb_result *res;
514 res = talloc_zero(tmp_ctx, struct ldb_result);
516 talloc_free(tmp_ctx);
517 return ldb_oom(ldb_module_get_ctx(module));
520 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
524 ldb_modify_default_callback,
526 LDB_REQ_SET_LOCATION(req);
527 if (ret != LDB_SUCCESS) {
528 talloc_free(tmp_ctx);
532 ret = dsdb_request_add_controls(req, dsdb_flags);
533 if (ret != LDB_SUCCESS) {
534 talloc_free(tmp_ctx);
538 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
539 ldb_req_mark_trusted(req);
542 /* Run the new request */
543 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
544 ret = ldb_next_request(module, req);
545 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
546 ret = ldb_request(ldb_module_get_ctx(module), req);
548 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
549 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
550 ret = ops->add(module, req);
552 if (ret == LDB_SUCCESS) {
553 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
556 talloc_free(tmp_ctx);
561 a ldb_delete request operating on modules below the
564 int dsdb_module_del(struct ldb_module *module,
567 struct ldb_request *parent)
569 struct ldb_request *req;
571 struct ldb_context *ldb = ldb_module_get_ctx(module);
572 TALLOC_CTX *tmp_ctx = talloc_new(module);
573 struct ldb_result *res;
575 res = talloc_zero(tmp_ctx, struct ldb_result);
577 talloc_free(tmp_ctx);
581 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
585 ldb_modify_default_callback,
587 LDB_REQ_SET_LOCATION(req);
588 if (ret != LDB_SUCCESS) {
589 talloc_free(tmp_ctx);
593 ret = dsdb_request_add_controls(req, dsdb_flags);
594 if (ret != LDB_SUCCESS) {
595 talloc_free(tmp_ctx);
599 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
600 ldb_req_mark_trusted(req);
603 /* Run the new request */
604 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
605 ret = ldb_next_request(module, req);
606 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
607 ret = ldb_request(ldb_module_get_ctx(module), req);
609 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
610 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
611 ret = ops->del(module, req);
613 if (ret == LDB_SUCCESS) {
614 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
617 talloc_free(tmp_ctx);
622 check if a single valued link has multiple non-deleted values
624 This is needed when we will be using the RELAX control to stop
625 ldb_tdb from checking single valued links
627 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
628 const struct ldb_message_element *el)
630 bool found_active = false;
633 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
634 el->num_values < 2) {
638 for (i=0; i<el->num_values; i++) {
639 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
641 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
650 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
651 struct GUID op_feature_guid, bool *feature_enabled)
654 struct ldb_context *ldb = ldb_module_get_ctx(module);
655 struct ldb_result *res;
656 struct ldb_dn *search_dn;
657 struct GUID search_guid;
658 const char *attrs[] = {"msDS-EnabledFeature", NULL};
661 struct ldb_message_element *el;
663 *feature_enabled = false;
665 tmp_ctx = talloc_new(ldb);
667 ret = ldb_search(ldb, tmp_ctx, &res,
668 scope, LDB_SCOPE_BASE, attrs,
670 if (ret != LDB_SUCCESS) {
671 ldb_asprintf_errstring(ldb,
672 "Could no find the scope object - dn: %s\n",
673 ldb_dn_get_linearized(scope));
674 talloc_free(tmp_ctx);
675 return LDB_ERR_OPERATIONS_ERROR;
677 if (res->msgs[0]->num_elements > 0) {
679 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
681 attrs[0] = "msDS-OptionalFeatureGUID";
683 for (i=0; i<el->num_values; i++) {
684 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
686 ret = ldb_search(ldb, tmp_ctx, &res,
687 search_dn, LDB_SCOPE_BASE, attrs,
689 if (ret != LDB_SUCCESS) {
690 ldb_asprintf_errstring(ldb,
691 "Could no find object dn: %s\n",
692 ldb_dn_get_linearized(search_dn));
693 talloc_free(tmp_ctx);
694 return LDB_ERR_OPERATIONS_ERROR;
697 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
699 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
700 *feature_enabled = true;
705 talloc_free(tmp_ctx);
710 find the NTDS GUID from a computers DN record
712 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
714 struct ldb_dn *computer_dn,
715 struct GUID *ntds_guid,
716 struct ldb_request *parent)
721 *ntds_guid = GUID_zero();
723 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
724 "serverReferenceBL", &dn, parent);
725 if (ret != LDB_SUCCESS) {
729 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
731 return LDB_ERR_OPERATIONS_ERROR;
734 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
740 find a 'reference' DN that points at another object
741 (eg. serverReference, rIDManagerReference etc)
743 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
744 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
746 const char *attrs[2];
747 struct ldb_result *res;
750 attrs[0] = attribute;
753 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
754 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
755 if (ret != LDB_SUCCESS) {
759 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
760 mem_ctx, res->msgs[0], attribute);
762 ldb_reset_err_string(ldb_module_get_ctx(module));
764 return LDB_ERR_NO_SUCH_ATTRIBUTE;
772 find the RID Manager$ DN via the rIDManagerReference attribute in the
775 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
776 struct ldb_request *parent)
778 return dsdb_module_reference_dn(module, mem_ctx,
779 ldb_get_default_basedn(ldb_module_get_ctx(module)),
780 "rIDManagerReference", dn, parent);
784 used to chain to the callers callback
786 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
788 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
790 talloc_steal(up_req, req);
791 return up_req->callback(up_req, ares);
795 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
796 object for a partition
798 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
799 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
801 struct ldb_context *ldb = ldb_module_get_ctx(module);
802 struct ldb_request *req;
804 TALLOC_CTX *tmp_ctx = talloc_new(module);
805 struct dsdb_control_current_partition *p_ctrl;
806 struct ldb_result *res;
808 res = talloc_zero(tmp_ctx, struct ldb_result);
810 talloc_free(tmp_ctx);
811 return ldb_module_oom(module);
814 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
815 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
819 res, ldb_search_default_callback,
821 LDB_REQ_SET_LOCATION(req);
822 if (ret != LDB_SUCCESS) {
823 talloc_free(tmp_ctx);
827 p_ctrl = talloc(req, struct dsdb_control_current_partition);
828 if (p_ctrl == NULL) {
829 talloc_free(tmp_ctx);
830 return ldb_module_oom(module);
832 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
836 ret = ldb_request_add_control(req,
837 DSDB_CONTROL_CURRENT_PARTITION_OID,
839 if (ret != LDB_SUCCESS) {
840 talloc_free(tmp_ctx);
844 /* Run the new request */
845 ret = ldb_next_request(module, req);
847 if (ret == LDB_SUCCESS) {
848 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
851 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
852 /* it hasn't been created yet, which means
853 an implicit value of zero */
855 talloc_free(tmp_ctx);
856 ldb_reset_err_string(ldb);
860 if (ret != LDB_SUCCESS) {
861 talloc_free(tmp_ctx);
865 if (res->count != 1) {
871 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
873 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
877 talloc_free(tmp_ctx);
883 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
886 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
887 uint64_t uSN, uint64_t urgent_uSN,
888 struct ldb_request *parent)
890 struct ldb_context *ldb = ldb_module_get_ctx(module);
891 struct ldb_request *req;
892 struct ldb_message *msg;
893 struct dsdb_control_current_partition *p_ctrl;
895 struct ldb_result *res;
897 msg = ldb_msg_new(module);
899 return ldb_module_oom(module);
902 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
903 if (msg->dn == NULL) {
905 return ldb_operr(ldb_module_get_ctx(module));
908 res = talloc_zero(msg, struct ldb_result);
911 return ldb_module_oom(module);
914 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
915 if (ret != LDB_SUCCESS) {
919 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
921 /* urgent_uSN is optional so may not be stored */
923 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
925 if (ret != LDB_SUCCESS) {
929 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
933 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
934 if (p_ctrl == NULL) {
938 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
940 ret = ldb_build_mod_req(&req, ldb, msg,
944 ldb_modify_default_callback,
946 LDB_REQ_SET_LOCATION(req);
948 if (ret != LDB_SUCCESS) {
953 ret = ldb_request_add_control(req,
954 DSDB_CONTROL_CURRENT_PARTITION_OID,
956 if (ret != LDB_SUCCESS) {
961 /* Run the new request */
962 ret = ldb_next_request(module, req);
964 if (ret == LDB_SUCCESS) {
965 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
967 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
968 ret = ldb_build_add_req(&req, ldb, msg,
972 ldb_modify_default_callback,
974 LDB_REQ_SET_LOCATION(req);
983 bool dsdb_module_am_system(struct ldb_module *module)
985 struct ldb_context *ldb = ldb_module_get_ctx(module);
986 struct auth_session_info *session_info
987 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
988 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
991 bool dsdb_module_am_administrator(struct ldb_module *module)
993 struct ldb_context *ldb = ldb_module_get_ctx(module);
994 struct auth_session_info *session_info
995 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
996 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1000 check if the recyclebin is enabled
1002 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1004 struct ldb_context *ldb = ldb_module_get_ctx(module);
1005 struct ldb_dn *partitions_dn;
1006 struct GUID recyclebin_guid;
1009 partitions_dn = samdb_partitions_dn(ldb, module);
1011 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1013 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
1014 if (ret != LDB_SUCCESS) {
1015 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1016 talloc_free(partitions_dn);
1017 return LDB_ERR_UNWILLING_TO_PERFORM;
1020 talloc_free(partitions_dn);
1024 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1025 struct ldb_message *msg,
1027 const int32_t *old_val,
1028 const int32_t *new_val)
1030 struct ldb_message_element *el;
1035 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1036 if (ret != LDB_SUCCESS) {
1040 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1042 return ldb_module_oom(module);
1044 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1046 return ldb_module_oom(module);
1048 *el->values = data_blob_string_const(vstring);
1052 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1053 if (ret != LDB_SUCCESS) {
1057 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1059 return ldb_module_oom(module);
1061 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1063 return ldb_module_oom(module);
1065 *el->values = data_blob_string_const(vstring);
1071 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1072 struct ldb_message *msg,
1074 const uint32_t *old_val,
1075 const uint32_t *new_val)
1077 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1078 (const int32_t *)old_val,
1079 (const int32_t *)new_val);
1082 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1083 struct ldb_message *msg,
1085 const int64_t *old_val,
1086 const int64_t *new_val)
1088 struct ldb_message_element *el;
1093 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1094 if (ret != LDB_SUCCESS) {
1098 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1100 return ldb_module_oom(module);
1102 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1104 return ldb_module_oom(module);
1106 *el->values = data_blob_string_const(vstring);
1110 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1111 if (ret != LDB_SUCCESS) {
1115 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1117 return ldb_module_oom(module);
1119 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1121 return ldb_module_oom(module);
1123 *el->values = data_blob_string_const(vstring);
1129 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1130 struct ldb_message *msg,
1132 const uint64_t *old_val,
1133 const uint64_t *new_val)
1135 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1136 (const int64_t *)old_val,
1137 (const int64_t *)new_val);
1141 update an int32 attribute safely via a constrained delete/add
1143 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1146 const int32_t *old_val,
1147 const int32_t *new_val,
1148 struct ldb_request *parent)
1150 struct ldb_message *msg;
1153 msg = ldb_msg_new(module);
1156 ret = dsdb_msg_constrainted_update_int32(module,
1160 if (ret != LDB_SUCCESS) {
1165 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1170 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1173 const uint32_t *old_val,
1174 const uint32_t *new_val,
1175 struct ldb_request *parent)
1177 return dsdb_module_constrainted_update_int32(module, dn, attr,
1178 (const int32_t *)old_val,
1179 (const int32_t *)new_val, parent);
1183 update an int64 attribute safely via a constrained delete/add
1185 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1188 const int64_t *old_val,
1189 const int64_t *new_val,
1190 struct ldb_request *parent)
1192 struct ldb_message *msg;
1195 msg = ldb_msg_new(module);
1198 ret = dsdb_msg_constrainted_update_int64(module,
1202 if (ret != LDB_SUCCESS) {
1207 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1212 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1215 const uint64_t *old_val,
1216 const uint64_t *new_val,
1217 struct ldb_request *parent)
1219 return dsdb_module_constrainted_update_int64(module, dn, attr,
1220 (const int64_t *)old_val,
1221 (const int64_t *)new_val,
1226 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1227 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1230 struct ldb_dn *new_dn;
1231 struct ldb_context *ldb = ldb_module_get_ctx(module);
1232 static const char *attrs[] = { "dSHeuristics", NULL };
1233 struct ldb_result *res;
1235 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1236 if (!ldb_dn_add_child_fmt(new_dn,
1237 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1238 talloc_free(new_dn);
1241 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1244 DSDB_FLAG_NEXT_MODULE,
1246 if (ret == LDB_SUCCESS && res->count == 1) {
1247 talloc_free(new_dn);
1248 return ldb_msg_find_ldb_val(res->msgs[0],
1251 talloc_free(new_dn);
1255 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1257 TALLOC_CTX *tmp_ctx = talloc_new(module);
1259 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1261 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1263 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1269 talloc_free(tmp_ctx);
1273 bool dsdb_user_password_support(struct ldb_module *module,
1274 TALLOC_CTX *mem_ctx,
1275 struct ldb_request *parent)
1277 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1279 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1282 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1284 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1285 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1291 talloc_free(tmp_ctx);
1296 show the chain of requests, useful for debugging async requests
1298 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1300 char *s = ldb_module_call_chain(req, req);
1301 DEBUG(level, ("%s\n", s));
1306 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1307 * performing a modify operation.
1309 * In order that the constraint checking by the "objectclass_attrs" LDB module
1310 * does work properly, the change request should remain similar or only be
1311 * enhanced (no other modifications as deletions, variations).
1313 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1314 const char *attr_name,
1315 enum ldb_request_type operation)
1317 struct ldb_message_element *el = NULL;
1320 /* We've to walk over all modification entries and consider the last
1321 * non-delete one which belongs to "attr_name".
1323 * If "el" is NULL afterwards then that means there was no interesting
1325 for (i = 0; i < msg->num_elements; i++) {
1326 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1327 if ((operation == LDB_MODIFY) &&
1328 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1329 == LDB_FLAG_MOD_DELETE)) {
1332 el = &msg->elements[i];