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"
30 #include "lib/ldb/include/ldb_private.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,
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 /* Run the new request */
77 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
78 ret = ldb_next_request(module, req);
79 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
80 ret = ldb_request(ldb_module_get_ctx(module), req);
82 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
83 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
84 ret = ops->search(module, req);
86 if (ret == LDB_SUCCESS) {
87 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
90 if (ret != LDB_SUCCESS) {
95 if (res->count != 1) {
96 /* we may be reading a DB that does not have the 'check base on search' option... */
97 ret = LDB_ERR_NO_SUCH_OBJECT;
98 ldb_asprintf_errstring(ldb_module_get_ctx(module),
99 "dsdb_module_search_dn: did not find base dn %s (%d results)",
100 ldb_dn_get_linearized(basedn), res->count);
102 *_res = talloc_steal(mem_ctx, res);
104 talloc_free(tmp_ctx);
109 search for attrs in the modules below
111 int dsdb_module_search(struct ldb_module *module,
113 struct ldb_result **_res,
114 struct ldb_dn *basedn, enum ldb_scope scope,
115 const char * const *attrs,
117 const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
120 struct ldb_request *req;
122 struct ldb_result *res;
126 tmp_ctx = talloc_new(mem_ctx);
129 va_start(ap, format);
130 expression = talloc_vasprintf(tmp_ctx, format, ap);
134 talloc_free(tmp_ctx);
135 return ldb_oom(ldb_module_get_ctx(module));
141 res = talloc_zero(tmp_ctx, struct ldb_result);
143 talloc_free(tmp_ctx);
144 return ldb_oom(ldb_module_get_ctx(module));
147 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
154 ldb_search_default_callback,
156 LDB_REQ_SET_LOCATION(req);
157 if (ret != LDB_SUCCESS) {
158 talloc_free(tmp_ctx);
162 ret = dsdb_request_add_controls(req, dsdb_flags);
163 if (ret != LDB_SUCCESS) {
164 talloc_free(tmp_ctx);
168 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
169 ret = ldb_next_request(module, req);
170 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
171 ret = ldb_request(ldb_module_get_ctx(module), req);
173 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
174 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
175 ret = ops->search(module, req);
177 if (ret == LDB_SUCCESS) {
178 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
182 if (ret == LDB_SUCCESS) {
183 *_res = talloc_steal(mem_ctx, res);
185 talloc_free(tmp_ctx);
190 find a DN given a GUID. This searches across all partitions
192 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
193 const struct GUID *guid, struct ldb_dn **dn)
195 struct ldb_result *res;
196 const char *attrs[] = { NULL };
197 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
200 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
202 DSDB_FLAG_NEXT_MODULE |
203 DSDB_SEARCH_SHOW_DELETED |
204 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
205 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
206 "objectGUID=%s", GUID_string(tmp_ctx, guid));
207 if (ret != LDB_SUCCESS) {
208 talloc_free(tmp_ctx);
211 if (res->count == 0) {
212 talloc_free(tmp_ctx);
213 return LDB_ERR_NO_SUCH_OBJECT;
215 if (res->count != 1) {
216 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
217 GUID_string(tmp_ctx, guid));
218 talloc_free(tmp_ctx);
219 return LDB_ERR_OPERATIONS_ERROR;
222 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
224 talloc_free(tmp_ctx);
229 find a GUID given a DN.
231 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
233 const char *attrs[] = { NULL };
234 struct ldb_result *res;
235 TALLOC_CTX *tmp_ctx = talloc_new(module);
239 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
240 DSDB_FLAG_NEXT_MODULE |
241 DSDB_SEARCH_SHOW_DELETED |
242 DSDB_SEARCH_SHOW_EXTENDED_DN);
243 if (ret != LDB_SUCCESS) {
244 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
245 ldb_dn_get_linearized(dn));
246 talloc_free(tmp_ctx);
250 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
251 if (!NT_STATUS_IS_OK(status)) {
252 talloc_free(tmp_ctx);
253 return ldb_operr(ldb_module_get_ctx(module));
256 talloc_free(tmp_ctx);
261 a ldb_modify request operating on modules below the
264 int dsdb_module_modify(struct ldb_module *module,
265 const struct ldb_message *message,
268 struct ldb_request *mod_req;
270 struct ldb_context *ldb = ldb_module_get_ctx(module);
271 TALLOC_CTX *tmp_ctx = talloc_new(module);
272 struct ldb_result *res;
274 res = talloc_zero(tmp_ctx, struct ldb_result);
276 talloc_free(tmp_ctx);
277 return ldb_oom(ldb_module_get_ctx(module));
280 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
284 ldb_modify_default_callback,
286 LDB_REQ_SET_LOCATION(mod_req);
287 if (ret != LDB_SUCCESS) {
288 talloc_free(tmp_ctx);
292 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
293 if (ret != LDB_SUCCESS) {
294 talloc_free(tmp_ctx);
298 /* Run the new request */
299 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
300 ret = ldb_next_request(module, mod_req);
301 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
302 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
304 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
305 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
306 ret = ops->modify(module, mod_req);
308 if (ret == LDB_SUCCESS) {
309 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
312 talloc_free(tmp_ctx);
319 a ldb_rename request operating on modules below the
322 int dsdb_module_rename(struct ldb_module *module,
323 struct ldb_dn *olddn, struct ldb_dn *newdn,
326 struct ldb_request *req;
328 struct ldb_context *ldb = ldb_module_get_ctx(module);
329 TALLOC_CTX *tmp_ctx = talloc_new(module);
330 struct ldb_result *res;
332 res = talloc_zero(tmp_ctx, struct ldb_result);
334 talloc_free(tmp_ctx);
335 return ldb_oom(ldb_module_get_ctx(module));
338 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
343 ldb_modify_default_callback,
345 LDB_REQ_SET_LOCATION(req);
346 if (ret != LDB_SUCCESS) {
347 talloc_free(tmp_ctx);
351 ret = dsdb_request_add_controls(req, dsdb_flags);
352 if (ret != LDB_SUCCESS) {
353 talloc_free(tmp_ctx);
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->rename(module, req);
367 if (ret == LDB_SUCCESS) {
368 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
371 talloc_free(tmp_ctx);
376 a ldb_add request operating on modules below the
379 int dsdb_module_add(struct ldb_module *module,
380 const struct ldb_message *message,
383 struct ldb_request *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_add_req(&req, ldb, tmp_ctx,
399 ldb_modify_default_callback,
401 LDB_REQ_SET_LOCATION(req);
402 if (ret != LDB_SUCCESS) {
403 talloc_free(tmp_ctx);
407 ret = dsdb_request_add_controls(req, dsdb_flags);
408 if (ret != LDB_SUCCESS) {
409 talloc_free(tmp_ctx);
413 /* Run the new request */
414 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
415 ret = ldb_next_request(module, req);
416 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
417 ret = ldb_request(ldb_module_get_ctx(module), req);
419 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
420 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
421 ret = ops->add(module, req);
423 if (ret == LDB_SUCCESS) {
424 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
427 talloc_free(tmp_ctx);
432 a ldb_delete request operating on modules below the
435 int dsdb_module_del(struct ldb_module *module,
439 struct ldb_request *req;
441 struct ldb_context *ldb = ldb_module_get_ctx(module);
442 TALLOC_CTX *tmp_ctx = talloc_new(module);
443 struct ldb_result *res;
445 res = talloc_zero(tmp_ctx, struct ldb_result);
447 talloc_free(tmp_ctx);
451 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
455 ldb_modify_default_callback,
457 LDB_REQ_SET_LOCATION(req);
458 if (ret != LDB_SUCCESS) {
459 talloc_free(tmp_ctx);
463 ret = dsdb_request_add_controls(req, dsdb_flags);
464 if (ret != LDB_SUCCESS) {
465 talloc_free(tmp_ctx);
469 /* Run the new request */
470 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
471 ret = ldb_next_request(module, req);
472 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
473 ret = ldb_request(ldb_module_get_ctx(module), req);
475 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
476 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
477 ret = ops->del(module, req);
479 if (ret == LDB_SUCCESS) {
480 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
483 talloc_free(tmp_ctx);
487 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
489 const struct dsdb_class *last_class = NULL;
492 for (i = 0; i < element->num_values; i++){
493 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
495 if(tmp_class == NULL) {
499 if(tmp_class->objectClassCategory > 1) {
504 last_class = tmp_class;
506 if (tmp_class->subClass_order > last_class->subClass_order)
507 last_class = tmp_class;
515 check if a single valued link has multiple non-deleted values
517 This is needed when we will be using the RELAX control to stop
518 ldb_tdb from checking single valued links
520 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
521 const struct ldb_message_element *el)
523 bool found_active = false;
526 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
527 el->num_values < 2) {
531 for (i=0; i<el->num_values; i++) {
532 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
534 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
543 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
544 struct GUID op_feature_guid, bool *feature_enabled)
547 struct ldb_context *ldb = ldb_module_get_ctx(module);
548 struct ldb_result *res;
549 struct ldb_dn *search_dn;
550 struct GUID search_guid;
551 const char *attrs[] = {"msDS-EnabledFeature", NULL};
554 struct ldb_message_element *el;
556 *feature_enabled = false;
558 tmp_ctx = talloc_new(ldb);
560 ret = ldb_search(ldb, tmp_ctx, &res,
561 scope, LDB_SCOPE_BASE, attrs,
563 if (ret != LDB_SUCCESS) {
564 ldb_asprintf_errstring(ldb,
565 "Could no find the scope object - dn: %s\n",
566 ldb_dn_get_linearized(scope));
567 talloc_free(tmp_ctx);
568 return LDB_ERR_OPERATIONS_ERROR;
570 if (res->msgs[0]->num_elements > 0) {
572 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
574 attrs[0] = "msDS-OptionalFeatureGUID";
576 for (i=0; i<el->num_values; i++) {
577 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
579 ret = ldb_search(ldb, tmp_ctx, &res,
580 search_dn, LDB_SCOPE_BASE, attrs,
582 if (ret != LDB_SUCCESS) {
583 ldb_asprintf_errstring(ldb,
584 "Could no find object dn: %s\n",
585 ldb_dn_get_linearized(search_dn));
586 talloc_free(tmp_ctx);
587 return LDB_ERR_OPERATIONS_ERROR;
590 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
592 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
593 *feature_enabled = true;
598 talloc_free(tmp_ctx);
603 find a 'reference' DN that points at another object
604 (eg. serverReference, rIDManagerReference etc)
606 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
607 const char *attribute, struct ldb_dn **dn)
609 const char *attrs[2];
610 struct ldb_result *res;
613 attrs[0] = attribute;
616 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
617 DSDB_FLAG_NEXT_MODULE);
618 if (ret != LDB_SUCCESS) {
622 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
623 mem_ctx, res->msgs[0], attribute);
625 ldb_reset_err_string(ldb_module_get_ctx(module));
627 return LDB_ERR_NO_SUCH_ATTRIBUTE;
635 find the RID Manager$ DN via the rIDManagerReference attribute in the
638 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
640 return dsdb_module_reference_dn(module, mem_ctx,
641 ldb_get_default_basedn(ldb_module_get_ctx(module)),
642 "rIDManagerReference", dn);
647 update an integer attribute safely via a constrained delete/add
649 int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
650 const char *attr, uint64_t old_val, uint64_t new_val)
652 struct ldb_message *msg;
653 struct ldb_message_element *el;
654 struct ldb_val v1, v2;
658 msg = ldb_msg_new(module);
661 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
662 if (ret != LDB_SUCCESS) {
668 vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
671 return ldb_module_oom(module);
673 v1 = data_blob_string_const(vstring);
675 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
676 if (ret != LDB_SUCCESS) {
682 vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
685 return ldb_module_oom(module);
687 v2 = data_blob_string_const(vstring);
689 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
695 used to chain to the callers callback
697 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
699 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
701 talloc_steal(up_req, req);
702 return up_req->callback(up_req, ares);
707 set an integer attribute
709 int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
710 const char *attr, uint64_t new_val)
712 struct ldb_message *msg;
715 msg = ldb_msg_new(module);
718 ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
719 if (ret != LDB_SUCCESS) {
723 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
725 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
731 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
732 object for a partition
734 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
735 uint64_t *uSN, uint64_t *urgent_uSN)
737 struct ldb_context *ldb = ldb_module_get_ctx(module);
738 struct ldb_request *req;
740 TALLOC_CTX *tmp_ctx = talloc_new(module);
741 struct dsdb_control_current_partition *p_ctrl;
742 struct ldb_result *res;
744 res = talloc_zero(tmp_ctx, struct ldb_result);
746 talloc_free(tmp_ctx);
747 return ldb_module_oom(module);
750 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
751 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
755 res, ldb_search_default_callback,
757 LDB_REQ_SET_LOCATION(req);
758 if (ret != LDB_SUCCESS) {
759 talloc_free(tmp_ctx);
763 p_ctrl = talloc(req, struct dsdb_control_current_partition);
764 if (p_ctrl == NULL) {
765 talloc_free(tmp_ctx);
766 return ldb_module_oom(module);
768 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
772 ret = ldb_request_add_control(req,
773 DSDB_CONTROL_CURRENT_PARTITION_OID,
775 if (ret != LDB_SUCCESS) {
776 talloc_free(tmp_ctx);
780 /* Run the new request */
781 ret = ldb_next_request(module, req);
783 if (ret == LDB_SUCCESS) {
784 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
787 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
788 /* it hasn't been created yet, which means
789 an implicit value of zero */
791 talloc_free(tmp_ctx);
795 if (ret != LDB_SUCCESS) {
796 talloc_free(tmp_ctx);
800 if (res->count != 1) {
806 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
808 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
812 talloc_free(tmp_ctx);
818 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
821 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
822 uint64_t uSN, uint64_t urgent_uSN)
824 struct ldb_context *ldb = ldb_module_get_ctx(module);
825 struct ldb_request *req;
826 struct ldb_message *msg;
827 struct dsdb_control_current_partition *p_ctrl;
829 struct ldb_result *res;
831 msg = ldb_msg_new(module);
833 return ldb_module_oom(module);
836 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
837 if (msg->dn == NULL) {
839 return ldb_operr(ldb_module_get_ctx(module));
842 res = talloc_zero(msg, struct ldb_result);
845 return ldb_module_oom(module);
848 ret = ldb_msg_add_fmt(msg, "uSNHighest", "%llu", (unsigned long long)uSN);
849 if (ret != LDB_SUCCESS) {
853 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
855 /* urgent_uSN is optional so may not be stored */
857 ret = ldb_msg_add_fmt(msg, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN);
858 if (ret != LDB_SUCCESS) {
862 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
866 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
867 if (p_ctrl == NULL) {
871 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
873 ret = ldb_build_mod_req(&req, ldb, msg,
877 ldb_modify_default_callback,
879 LDB_REQ_SET_LOCATION(req);
881 if (ret != LDB_SUCCESS) {
886 ret = ldb_request_add_control(req,
887 DSDB_CONTROL_CURRENT_PARTITION_OID,
889 if (ret != LDB_SUCCESS) {
894 /* Run the new request */
895 ret = ldb_next_request(module, req);
897 if (ret == LDB_SUCCESS) {
898 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
900 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
901 ret = ldb_build_add_req(&req, ldb, msg,
905 ldb_modify_default_callback,
907 LDB_REQ_SET_LOCATION(req);
916 bool dsdb_module_am_system(struct ldb_module *module)
918 struct ldb_context *ldb = ldb_module_get_ctx(module);
919 struct auth_session_info *session_info
920 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
921 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
924 bool dsdb_module_am_administrator(struct ldb_module *module)
926 struct ldb_context *ldb = ldb_module_get_ctx(module);
927 struct auth_session_info *session_info
928 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
929 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
933 check if the recyclebin is enabled
935 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
937 struct ldb_context *ldb = ldb_module_get_ctx(module);
938 struct ldb_dn *partitions_dn;
939 struct GUID recyclebin_guid;
942 partitions_dn = samdb_partitions_dn(ldb, module);
944 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
946 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
947 if (ret != LDB_SUCCESS) {
948 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
949 talloc_free(partitions_dn);
950 return LDB_ERR_UNWILLING_TO_PERFORM;
953 talloc_free(partitions_dn);
957 bool is_attr_in_list(const char * const * attrs, const char *attr)
961 for (i = 0; attrs[i]; i++) {
962 if (ldb_attr_cmp(attrs[i], attr) == 0)
969 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
970 struct ldb_message *msg,
972 const int32_t *old_val,
973 const int32_t *new_val)
975 struct ldb_message_element *el;
980 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
981 if (ret != LDB_SUCCESS) {
985 el->values = talloc_array(msg, struct ldb_val, el->num_values);
987 return ldb_module_oom(module);
989 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
991 return ldb_module_oom(module);
993 *el->values = data_blob_string_const(vstring);
997 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
998 if (ret != LDB_SUCCESS) {
1002 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1004 return ldb_module_oom(module);
1006 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1008 return ldb_module_oom(module);
1010 *el->values = data_blob_string_const(vstring);
1016 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1017 struct ldb_message *msg,
1019 const uint32_t *old_val,
1020 const uint32_t *new_val)
1022 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1023 (const int32_t *)old_val,
1024 (const int32_t *)new_val);
1027 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1028 struct ldb_message *msg,
1030 const int64_t *old_val,
1031 const int64_t *new_val)
1033 struct ldb_message_element *el;
1038 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1039 if (ret != LDB_SUCCESS) {
1043 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1045 return ldb_module_oom(module);
1047 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1049 return ldb_module_oom(module);
1051 *el->values = data_blob_string_const(vstring);
1055 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1056 if (ret != LDB_SUCCESS) {
1060 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1062 return ldb_module_oom(module);
1064 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1066 return ldb_module_oom(module);
1068 *el->values = data_blob_string_const(vstring);
1074 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1075 struct ldb_message *msg,
1077 const uint64_t *old_val,
1078 const uint64_t *new_val)
1080 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1081 (const int64_t *)old_val,
1082 (const int64_t *)new_val);
1086 update an int32 attribute safely via a constrained delete/add
1088 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1091 const int32_t *old_val,
1092 const int32_t *new_val)
1094 struct ldb_message *msg;
1097 msg = ldb_msg_new(module);
1100 ret = dsdb_msg_constrainted_update_int32(module,
1104 if (ret != LDB_SUCCESS) {
1109 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1114 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1117 const uint32_t *old_val,
1118 const uint32_t *new_val)
1120 return dsdb_module_constrainted_update_int32(module, dn, attr,
1121 (const int32_t *)old_val,
1122 (const int32_t *)new_val);
1126 update an int64 attribute safely via a constrained delete/add
1128 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1131 const int64_t *old_val,
1132 const int64_t *new_val)
1134 struct ldb_message *msg;
1137 msg = ldb_msg_new(module);
1140 ret = dsdb_msg_constrainted_update_int64(module,
1144 if (ret != LDB_SUCCESS) {
1149 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1154 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1157 const uint64_t *old_val,
1158 const uint64_t *new_val)
1160 return dsdb_module_constrainted_update_int64(module, dn, attr,
1161 (const int64_t *)old_val,
1162 (const int64_t *)new_val);
1166 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1167 TALLOC_CTX *mem_ctx)
1170 struct ldb_dn *new_dn;
1171 struct ldb_context *ldb = ldb_module_get_ctx(module);
1172 static const char *attrs[] = { "dsHeuristics", NULL };
1173 struct ldb_result *res;
1175 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1176 if (!ldb_dn_add_child_fmt(new_dn,
1177 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1178 talloc_free(new_dn);
1181 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1184 DSDB_FLAG_NEXT_MODULE);
1185 if (ret == LDB_SUCCESS && res->count == 1) {
1186 talloc_free(new_dn);
1187 return ldb_msg_find_ldb_val(res->msgs[0],
1190 talloc_free(new_dn);
1194 bool dsdb_block_anonymous_ops(struct ldb_module *module,
1195 TALLOC_CTX *mem_ctx)
1197 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1199 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1201 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1203 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1209 talloc_free(tmp_ctx);
1214 show the chain of requests, useful for debugging async requests
1216 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1220 while (req && req->handle) {
1221 DEBUG(level,("req[%u] %p : %s\n", i++, req, ldb_req_location(req)));
1222 req = req->handle->parent;