2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 2009
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "ldb_module.h"
25 #include "librpc/ndr/libndr.h"
26 #include "dsdb/samdb/ldb_modules/util.h"
27 #include "dsdb/samdb/samdb.h"
29 #include "libcli/security/security.h"
32 search for attrs on one DN, in the modules below
34 int dsdb_module_search_dn(struct ldb_module *module,
36 struct ldb_result **_res,
37 struct ldb_dn *basedn,
38 const char * const *attrs,
40 struct ldb_request *parent)
43 struct ldb_request *req;
45 struct ldb_result *res;
47 tmp_ctx = talloc_new(mem_ctx);
49 res = talloc_zero(tmp_ctx, struct ldb_result);
52 return ldb_oom(ldb_module_get_ctx(module));
55 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
62 ldb_search_default_callback,
64 LDB_REQ_SET_LOCATION(req);
65 if (ret != LDB_SUCCESS) {
70 ret = dsdb_request_add_controls(req, dsdb_flags);
71 if (ret != LDB_SUCCESS) {
76 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
77 ldb_req_mark_trusted(req);
80 /* Run the new request */
81 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
82 ret = ldb_next_request(module, req);
83 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
84 ret = ldb_request(ldb_module_get_ctx(module), req);
86 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
87 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
88 ret = ops->search(module, req);
90 if (ret == LDB_SUCCESS) {
91 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
94 if (ret != LDB_SUCCESS) {
99 if (res->count != 1) {
100 /* we may be reading a DB that does not have the 'check base on search' option... */
101 ret = LDB_ERR_NO_SUCH_OBJECT;
102 ldb_asprintf_errstring(ldb_module_get_ctx(module),
103 "dsdb_module_search_dn: did not find base dn %s (%d results)",
104 ldb_dn_get_linearized(basedn), res->count);
106 *_res = talloc_steal(mem_ctx, res);
108 talloc_free(tmp_ctx);
112 int dsdb_module_search_tree(struct ldb_module *module,
114 struct ldb_result **_res,
115 struct ldb_dn *basedn,
116 enum ldb_scope scope,
117 struct ldb_parse_tree *tree,
118 const char * const *attrs,
120 struct ldb_request *parent)
123 struct ldb_request *req;
125 struct ldb_result *res;
127 tmp_ctx = talloc_new(mem_ctx);
130 res = talloc_zero(tmp_ctx, struct ldb_result);
132 talloc_free(tmp_ctx);
133 return ldb_oom(ldb_module_get_ctx(module));
136 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
143 ldb_search_default_callback,
145 LDB_REQ_SET_LOCATION(req);
146 if (ret != LDB_SUCCESS) {
147 talloc_free(tmp_ctx);
151 ret = dsdb_request_add_controls(req, dsdb_flags);
152 if (ret != LDB_SUCCESS) {
153 talloc_free(tmp_ctx);
157 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
158 ldb_req_mark_trusted(req);
161 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
162 ret = ldb_next_request(module, req);
163 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
164 ret = ldb_request(ldb_module_get_ctx(module), req);
166 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
167 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
168 ret = ops->search(module, req);
170 if (ret == LDB_SUCCESS) {
171 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
175 if (ret == LDB_SUCCESS) {
176 *_res = talloc_steal(mem_ctx, res);
178 talloc_free(tmp_ctx);
183 search for attrs in the modules below
185 int dsdb_module_search(struct ldb_module *module,
187 struct ldb_result **_res,
188 struct ldb_dn *basedn, enum ldb_scope scope,
189 const char * const *attrs,
191 struct ldb_request *parent,
192 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
198 struct ldb_parse_tree *tree;
200 tmp_ctx = talloc_new(mem_ctx);
203 va_start(ap, format);
204 expression = talloc_vasprintf(tmp_ctx, format, ap);
208 talloc_free(tmp_ctx);
209 return ldb_oom(ldb_module_get_ctx(module));
215 tree = ldb_parse_tree(tmp_ctx, expression);
217 talloc_free(tmp_ctx);
218 ldb_set_errstring(ldb_module_get_ctx(module),
219 "Unable to parse search expression");
220 return LDB_ERR_OPERATIONS_ERROR;
223 ret = dsdb_module_search_tree(module,
233 talloc_free(tmp_ctx);
238 find a DN given a GUID. This searches across all partitions
240 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
241 const struct GUID *guid, struct ldb_dn **dn,
242 struct ldb_request *parent)
244 struct ldb_result *res;
245 const char *attrs[] = { NULL };
246 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
249 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
251 DSDB_FLAG_NEXT_MODULE |
252 DSDB_SEARCH_SHOW_RECYCLED |
253 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
254 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
256 "objectGUID=%s", GUID_string(tmp_ctx, guid));
257 if (ret != LDB_SUCCESS) {
258 talloc_free(tmp_ctx);
261 if (res->count == 0) {
262 talloc_free(tmp_ctx);
263 return LDB_ERR_NO_SUCH_OBJECT;
265 if (res->count != 1) {
266 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
267 GUID_string(tmp_ctx, guid));
268 talloc_free(tmp_ctx);
269 return LDB_ERR_OPERATIONS_ERROR;
272 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
274 talloc_free(tmp_ctx);
279 find a GUID given a DN.
281 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
282 struct ldb_request *parent)
284 const char *attrs[] = { NULL };
285 struct ldb_result *res;
286 TALLOC_CTX *tmp_ctx = talloc_new(module);
290 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
291 DSDB_FLAG_NEXT_MODULE |
292 DSDB_SEARCH_SHOW_RECYCLED |
293 DSDB_SEARCH_SHOW_EXTENDED_DN,
295 if (ret != LDB_SUCCESS) {
296 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
297 ldb_dn_get_linearized(dn));
298 talloc_free(tmp_ctx);
302 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
303 if (!NT_STATUS_IS_OK(status)) {
304 talloc_free(tmp_ctx);
305 return ldb_operr(ldb_module_get_ctx(module));
308 talloc_free(tmp_ctx);
312 a ldb_extended request operating on modules below the
315 int dsdb_module_extended(struct ldb_module *module,
316 const char* oid, void* data,
318 struct ldb_request *parent)
320 struct ldb_request *req;
322 struct ldb_context *ldb = ldb_module_get_ctx(module);
323 TALLOC_CTX *tmp_ctx = talloc_new(module);
324 struct ldb_result *res;
326 res = talloc_zero(tmp_ctx, struct ldb_result);
328 talloc_free(tmp_ctx);
329 return ldb_oom(ldb_module_get_ctx(module));
332 ret = ldb_build_extended_req(&req, ldb,
337 res, ldb_extended_default_callback,
340 LDB_REQ_SET_LOCATION(req);
341 if (ret != LDB_SUCCESS) {
342 talloc_free(tmp_ctx);
346 ret = dsdb_request_add_controls(req, dsdb_flags);
347 if (ret != LDB_SUCCESS) {
348 talloc_free(tmp_ctx);
352 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
353 ldb_req_mark_trusted(req);
356 /* Run the new request */
357 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
358 ret = ldb_next_request(module, req);
359 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
360 ret = ldb_request(ldb_module_get_ctx(module), req);
362 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
363 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
364 ret = ops->extended(module, req);
366 if (ret == LDB_SUCCESS) {
367 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
370 talloc_free(tmp_ctx);
374 a ldb_modify request operating on modules below the
377 int dsdb_module_modify(struct ldb_module *module,
378 const struct ldb_message *message,
380 struct ldb_request *parent)
382 struct ldb_request *mod_req;
384 struct ldb_context *ldb = ldb_module_get_ctx(module);
385 TALLOC_CTX *tmp_ctx = talloc_new(module);
386 struct ldb_result *res;
388 res = talloc_zero(tmp_ctx, struct ldb_result);
390 talloc_free(tmp_ctx);
391 return ldb_oom(ldb_module_get_ctx(module));
394 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
398 ldb_modify_default_callback,
400 LDB_REQ_SET_LOCATION(mod_req);
401 if (ret != LDB_SUCCESS) {
402 talloc_free(tmp_ctx);
406 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
407 if (ret != LDB_SUCCESS) {
408 talloc_free(tmp_ctx);
412 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
413 ldb_req_mark_trusted(mod_req);
416 /* Run the new request */
417 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
418 ret = ldb_next_request(module, mod_req);
419 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
420 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
422 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
423 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
424 ret = ops->modify(module, mod_req);
426 if (ret == LDB_SUCCESS) {
427 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
430 talloc_free(tmp_ctx);
437 a ldb_rename request operating on modules below the
440 int dsdb_module_rename(struct ldb_module *module,
441 struct ldb_dn *olddn, struct ldb_dn *newdn,
443 struct ldb_request *parent)
445 struct ldb_request *req;
447 struct ldb_context *ldb = ldb_module_get_ctx(module);
448 TALLOC_CTX *tmp_ctx = talloc_new(module);
449 struct ldb_result *res;
451 res = talloc_zero(tmp_ctx, struct ldb_result);
453 talloc_free(tmp_ctx);
454 return ldb_oom(ldb_module_get_ctx(module));
457 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
462 ldb_modify_default_callback,
464 LDB_REQ_SET_LOCATION(req);
465 if (ret != LDB_SUCCESS) {
466 talloc_free(tmp_ctx);
470 ret = dsdb_request_add_controls(req, dsdb_flags);
471 if (ret != LDB_SUCCESS) {
472 talloc_free(tmp_ctx);
476 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
477 ldb_req_mark_trusted(req);
480 /* Run the new request */
481 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
482 ret = ldb_next_request(module, req);
483 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
484 ret = ldb_request(ldb_module_get_ctx(module), req);
486 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
487 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
488 ret = ops->rename(module, req);
490 if (ret == LDB_SUCCESS) {
491 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
494 talloc_free(tmp_ctx);
499 a ldb_add request operating on modules below the
502 int dsdb_module_add(struct ldb_module *module,
503 const struct ldb_message *message,
505 struct ldb_request *parent)
507 struct ldb_request *req;
509 struct ldb_context *ldb = ldb_module_get_ctx(module);
510 TALLOC_CTX *tmp_ctx = talloc_new(module);
511 struct ldb_result *res;
513 res = talloc_zero(tmp_ctx, struct ldb_result);
515 talloc_free(tmp_ctx);
516 return ldb_oom(ldb_module_get_ctx(module));
519 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
523 ldb_modify_default_callback,
525 LDB_REQ_SET_LOCATION(req);
526 if (ret != LDB_SUCCESS) {
527 talloc_free(tmp_ctx);
531 ret = dsdb_request_add_controls(req, dsdb_flags);
532 if (ret != LDB_SUCCESS) {
533 talloc_free(tmp_ctx);
537 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
538 ldb_req_mark_trusted(req);
541 /* Run the new request */
542 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
543 ret = ldb_next_request(module, req);
544 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
545 ret = ldb_request(ldb_module_get_ctx(module), req);
547 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
548 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
549 ret = ops->add(module, req);
551 if (ret == LDB_SUCCESS) {
552 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
555 talloc_free(tmp_ctx);
560 a ldb_delete request operating on modules below the
563 int dsdb_module_del(struct ldb_module *module,
566 struct ldb_request *parent)
568 struct ldb_request *req;
570 struct ldb_context *ldb = ldb_module_get_ctx(module);
571 TALLOC_CTX *tmp_ctx = talloc_new(module);
572 struct ldb_result *res;
574 res = talloc_zero(tmp_ctx, struct ldb_result);
576 talloc_free(tmp_ctx);
580 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
584 ldb_modify_default_callback,
586 LDB_REQ_SET_LOCATION(req);
587 if (ret != LDB_SUCCESS) {
588 talloc_free(tmp_ctx);
592 ret = dsdb_request_add_controls(req, dsdb_flags);
593 if (ret != LDB_SUCCESS) {
594 talloc_free(tmp_ctx);
598 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
599 ldb_req_mark_trusted(req);
602 /* Run the new request */
603 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
604 ret = ldb_next_request(module, req);
605 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
606 ret = ldb_request(ldb_module_get_ctx(module), req);
608 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
609 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
610 ret = ops->del(module, req);
612 if (ret == LDB_SUCCESS) {
613 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
616 talloc_free(tmp_ctx);
621 check if a single valued link has multiple non-deleted values
623 This is needed when we will be using the RELAX control to stop
624 ldb_tdb from checking single valued links
626 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
627 const struct ldb_message_element *el)
629 bool found_active = false;
632 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
633 el->num_values < 2) {
637 for (i=0; i<el->num_values; i++) {
638 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
640 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
649 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
650 struct GUID op_feature_guid, bool *feature_enabled)
653 struct ldb_context *ldb = ldb_module_get_ctx(module);
654 struct ldb_result *res;
655 struct ldb_dn *search_dn;
656 struct GUID search_guid;
657 const char *attrs[] = {"msDS-EnabledFeature", NULL};
660 struct ldb_message_element *el;
662 *feature_enabled = false;
664 tmp_ctx = talloc_new(ldb);
666 ret = ldb_search(ldb, tmp_ctx, &res,
667 scope, LDB_SCOPE_BASE, attrs,
669 if (ret != LDB_SUCCESS) {
670 ldb_asprintf_errstring(ldb,
671 "Could no find the scope object - dn: %s\n",
672 ldb_dn_get_linearized(scope));
673 talloc_free(tmp_ctx);
674 return LDB_ERR_OPERATIONS_ERROR;
676 if (res->msgs[0]->num_elements > 0) {
678 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
680 attrs[0] = "msDS-OptionalFeatureGUID";
682 for (i=0; i<el->num_values; i++) {
683 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
685 ret = ldb_search(ldb, tmp_ctx, &res,
686 search_dn, LDB_SCOPE_BASE, attrs,
688 if (ret != LDB_SUCCESS) {
689 ldb_asprintf_errstring(ldb,
690 "Could no find object dn: %s\n",
691 ldb_dn_get_linearized(search_dn));
692 talloc_free(tmp_ctx);
693 return LDB_ERR_OPERATIONS_ERROR;
696 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
698 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
699 *feature_enabled = true;
704 talloc_free(tmp_ctx);
709 find the NTDS GUID from a computers DN record
711 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
713 struct ldb_dn *computer_dn,
714 struct GUID *ntds_guid,
715 struct ldb_request *parent)
720 *ntds_guid = GUID_zero();
722 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
723 "serverReferenceBL", &dn, parent);
724 if (ret != LDB_SUCCESS) {
728 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
730 return LDB_ERR_OPERATIONS_ERROR;
733 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
739 find a 'reference' DN that points at another object
740 (eg. serverReference, rIDManagerReference etc)
742 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
743 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
745 const char *attrs[2];
746 struct ldb_result *res;
749 attrs[0] = attribute;
752 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
753 DSDB_FLAG_NEXT_MODULE, parent);
754 if (ret != LDB_SUCCESS) {
758 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
759 mem_ctx, res->msgs[0], attribute);
761 ldb_reset_err_string(ldb_module_get_ctx(module));
763 return LDB_ERR_NO_SUCH_ATTRIBUTE;
771 find the RID Manager$ DN via the rIDManagerReference attribute in the
774 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
775 struct ldb_request *parent)
777 return dsdb_module_reference_dn(module, mem_ctx,
778 ldb_get_default_basedn(ldb_module_get_ctx(module)),
779 "rIDManagerReference", dn, parent);
783 used to chain to the callers callback
785 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
787 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
789 talloc_steal(up_req, req);
790 return up_req->callback(up_req, ares);
794 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
795 object for a partition
797 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
798 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
800 struct ldb_context *ldb = ldb_module_get_ctx(module);
801 struct ldb_request *req;
803 TALLOC_CTX *tmp_ctx = talloc_new(module);
804 struct dsdb_control_current_partition *p_ctrl;
805 struct ldb_result *res;
807 res = talloc_zero(tmp_ctx, struct ldb_result);
809 talloc_free(tmp_ctx);
810 return ldb_module_oom(module);
813 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
814 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
818 res, ldb_search_default_callback,
820 LDB_REQ_SET_LOCATION(req);
821 if (ret != LDB_SUCCESS) {
822 talloc_free(tmp_ctx);
826 p_ctrl = talloc(req, struct dsdb_control_current_partition);
827 if (p_ctrl == NULL) {
828 talloc_free(tmp_ctx);
829 return ldb_module_oom(module);
831 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
835 ret = ldb_request_add_control(req,
836 DSDB_CONTROL_CURRENT_PARTITION_OID,
838 if (ret != LDB_SUCCESS) {
839 talloc_free(tmp_ctx);
843 /* Run the new request */
844 ret = ldb_next_request(module, req);
846 if (ret == LDB_SUCCESS) {
847 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
850 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
851 /* it hasn't been created yet, which means
852 an implicit value of zero */
854 talloc_free(tmp_ctx);
855 ldb_reset_err_string(ldb);
859 if (ret != LDB_SUCCESS) {
860 talloc_free(tmp_ctx);
864 if (res->count != 1) {
870 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
872 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
876 talloc_free(tmp_ctx);
882 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
885 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
886 uint64_t uSN, uint64_t urgent_uSN,
887 struct ldb_request *parent)
889 struct ldb_context *ldb = ldb_module_get_ctx(module);
890 struct ldb_request *req;
891 struct ldb_message *msg;
892 struct dsdb_control_current_partition *p_ctrl;
894 struct ldb_result *res;
896 msg = ldb_msg_new(module);
898 return ldb_module_oom(module);
901 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
902 if (msg->dn == NULL) {
904 return ldb_operr(ldb_module_get_ctx(module));
907 res = talloc_zero(msg, struct ldb_result);
910 return ldb_module_oom(module);
913 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
914 if (ret != LDB_SUCCESS) {
918 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
920 /* urgent_uSN is optional so may not be stored */
922 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
924 if (ret != LDB_SUCCESS) {
928 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
932 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
933 if (p_ctrl == NULL) {
937 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
939 ret = ldb_build_mod_req(&req, ldb, msg,
943 ldb_modify_default_callback,
945 LDB_REQ_SET_LOCATION(req);
947 if (ret != LDB_SUCCESS) {
952 ret = ldb_request_add_control(req,
953 DSDB_CONTROL_CURRENT_PARTITION_OID,
955 if (ret != LDB_SUCCESS) {
960 /* Run the new request */
961 ret = ldb_next_request(module, req);
963 if (ret == LDB_SUCCESS) {
964 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
966 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
967 ret = ldb_build_add_req(&req, ldb, msg,
971 ldb_modify_default_callback,
973 LDB_REQ_SET_LOCATION(req);
982 bool dsdb_module_am_system(struct ldb_module *module)
984 struct ldb_context *ldb = ldb_module_get_ctx(module);
985 struct auth_session_info *session_info
986 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
987 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
990 bool dsdb_module_am_administrator(struct ldb_module *module)
992 struct ldb_context *ldb = ldb_module_get_ctx(module);
993 struct auth_session_info *session_info
994 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
995 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
999 check if the recyclebin is enabled
1001 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1003 struct ldb_context *ldb = ldb_module_get_ctx(module);
1004 struct ldb_dn *partitions_dn;
1005 struct GUID recyclebin_guid;
1008 partitions_dn = samdb_partitions_dn(ldb, module);
1010 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1012 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
1013 if (ret != LDB_SUCCESS) {
1014 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1015 talloc_free(partitions_dn);
1016 return LDB_ERR_UNWILLING_TO_PERFORM;
1019 talloc_free(partitions_dn);
1023 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1024 struct ldb_message *msg,
1026 const int32_t *old_val,
1027 const int32_t *new_val)
1029 struct ldb_message_element *el;
1034 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1035 if (ret != LDB_SUCCESS) {
1039 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1041 return ldb_module_oom(module);
1043 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1045 return ldb_module_oom(module);
1047 *el->values = data_blob_string_const(vstring);
1051 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1052 if (ret != LDB_SUCCESS) {
1056 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1058 return ldb_module_oom(module);
1060 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1062 return ldb_module_oom(module);
1064 *el->values = data_blob_string_const(vstring);
1070 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1071 struct ldb_message *msg,
1073 const uint32_t *old_val,
1074 const uint32_t *new_val)
1076 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1077 (const int32_t *)old_val,
1078 (const int32_t *)new_val);
1081 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1082 struct ldb_message *msg,
1084 const int64_t *old_val,
1085 const int64_t *new_val)
1087 struct ldb_message_element *el;
1092 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1093 if (ret != LDB_SUCCESS) {
1097 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1099 return ldb_module_oom(module);
1101 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1103 return ldb_module_oom(module);
1105 *el->values = data_blob_string_const(vstring);
1109 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1110 if (ret != LDB_SUCCESS) {
1114 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1116 return ldb_module_oom(module);
1118 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1120 return ldb_module_oom(module);
1122 *el->values = data_blob_string_const(vstring);
1128 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1129 struct ldb_message *msg,
1131 const uint64_t *old_val,
1132 const uint64_t *new_val)
1134 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1135 (const int64_t *)old_val,
1136 (const int64_t *)new_val);
1140 update an int32 attribute safely via a constrained delete/add
1142 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1145 const int32_t *old_val,
1146 const int32_t *new_val,
1147 struct ldb_request *parent)
1149 struct ldb_message *msg;
1152 msg = ldb_msg_new(module);
1155 ret = dsdb_msg_constrainted_update_int32(module,
1159 if (ret != LDB_SUCCESS) {
1164 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1169 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1172 const uint32_t *old_val,
1173 const uint32_t *new_val,
1174 struct ldb_request *parent)
1176 return dsdb_module_constrainted_update_int32(module, dn, attr,
1177 (const int32_t *)old_val,
1178 (const int32_t *)new_val, parent);
1182 update an int64 attribute safely via a constrained delete/add
1184 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1187 const int64_t *old_val,
1188 const int64_t *new_val,
1189 struct ldb_request *parent)
1191 struct ldb_message *msg;
1194 msg = ldb_msg_new(module);
1197 ret = dsdb_msg_constrainted_update_int64(module,
1201 if (ret != LDB_SUCCESS) {
1206 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1211 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1214 const uint64_t *old_val,
1215 const uint64_t *new_val,
1216 struct ldb_request *parent)
1218 return dsdb_module_constrainted_update_int64(module, dn, attr,
1219 (const int64_t *)old_val,
1220 (const int64_t *)new_val,
1225 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1226 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1229 struct ldb_dn *new_dn;
1230 struct ldb_context *ldb = ldb_module_get_ctx(module);
1231 static const char *attrs[] = { "dSHeuristics", NULL };
1232 struct ldb_result *res;
1234 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1235 if (!ldb_dn_add_child_fmt(new_dn,
1236 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1237 talloc_free(new_dn);
1240 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1243 DSDB_FLAG_NEXT_MODULE,
1245 if (ret == LDB_SUCCESS && res->count == 1) {
1246 talloc_free(new_dn);
1247 return ldb_msg_find_ldb_val(res->msgs[0],
1250 talloc_free(new_dn);
1254 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1256 TALLOC_CTX *tmp_ctx = talloc_new(module);
1258 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1260 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1262 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1268 talloc_free(tmp_ctx);
1272 bool dsdb_user_password_support(struct ldb_module *module,
1273 TALLOC_CTX *mem_ctx,
1274 struct ldb_request *parent)
1276 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1278 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1281 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1283 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1284 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1290 talloc_free(tmp_ctx);
1295 show the chain of requests, useful for debugging async requests
1297 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1299 char *s = ldb_module_call_chain(req, req);
1300 DEBUG(level, ("%s\n", s));
1305 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1306 * performing a modify operation.
1308 * In order that the constraint checking by the "objectclass_attrs" LDB module
1309 * does work properly, the change request should remain similar or only be
1310 * enhanced (no other modifications as deletions, variations).
1312 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1313 const char *attr_name,
1314 enum ldb_request_type operation)
1316 struct ldb_message_element *el = NULL;
1319 /* We've to walk over all modification entries and consider the last
1320 * non-delete one which belongs to "attr_name".
1322 * If "el" is NULL afterwards then that means there was no interesting
1324 for (i = 0; i < msg->num_elements; i++) {
1325 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1326 if ((operation == LDB_MODIFY) &&
1327 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1328 == LDB_FLAG_MOD_DELETE)) {
1331 el = &msg->elements[i];