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"
31 #include "libcli/security/session.h"
34 search for attrs on one DN, in the modules below
36 int dsdb_module_search_dn(struct ldb_module *module,
38 struct ldb_result **_res,
39 struct ldb_dn *basedn,
40 const char * const *attrs,
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 /* Run the new request */
78 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
79 ret = ldb_next_request(module, req);
80 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
81 ret = ldb_request(ldb_module_get_ctx(module), req);
83 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
84 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
85 ret = ops->search(module, req);
87 if (ret == LDB_SUCCESS) {
88 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
91 if (ret != LDB_SUCCESS) {
96 if (res->count != 1) {
97 /* we may be reading a DB that does not have the 'check base on search' option... */
98 ret = LDB_ERR_NO_SUCH_OBJECT;
99 ldb_asprintf_errstring(ldb_module_get_ctx(module),
100 "dsdb_module_search_dn: did not find base dn %s (%d results)",
101 ldb_dn_get_linearized(basedn), res->count);
103 *_res = talloc_steal(mem_ctx, res);
105 talloc_free(tmp_ctx);
110 search for attrs in the modules below
112 int dsdb_module_search(struct ldb_module *module,
114 struct ldb_result **_res,
115 struct ldb_dn *basedn, enum ldb_scope scope,
116 const char * const *attrs,
118 const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
121 struct ldb_request *req;
123 struct ldb_result *res;
127 tmp_ctx = talloc_new(mem_ctx);
130 va_start(ap, format);
131 expression = talloc_vasprintf(tmp_ctx, format, ap);
135 talloc_free(tmp_ctx);
136 return ldb_oom(ldb_module_get_ctx(module));
142 res = talloc_zero(tmp_ctx, struct ldb_result);
144 talloc_free(tmp_ctx);
145 return ldb_oom(ldb_module_get_ctx(module));
148 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
155 ldb_search_default_callback,
157 LDB_REQ_SET_LOCATION(req);
158 if (ret != LDB_SUCCESS) {
159 talloc_free(tmp_ctx);
163 ret = dsdb_request_add_controls(req, dsdb_flags);
164 if (ret != LDB_SUCCESS) {
165 talloc_free(tmp_ctx);
169 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
170 ret = ldb_next_request(module, req);
171 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
172 ret = ldb_request(ldb_module_get_ctx(module), req);
174 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
175 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
176 ret = ops->search(module, req);
178 if (ret == LDB_SUCCESS) {
179 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
183 if (ret == LDB_SUCCESS) {
184 *_res = talloc_steal(mem_ctx, res);
186 talloc_free(tmp_ctx);
191 find a DN given a GUID. This searches across all partitions
193 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
194 const struct GUID *guid, struct ldb_dn **dn)
196 struct ldb_result *res;
197 const char *attrs[] = { NULL };
198 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
201 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
203 DSDB_FLAG_NEXT_MODULE |
204 DSDB_SEARCH_SHOW_RECYCLED |
205 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
206 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
207 "objectGUID=%s", GUID_string(tmp_ctx, guid));
208 if (ret != LDB_SUCCESS) {
209 talloc_free(tmp_ctx);
212 if (res->count == 0) {
213 talloc_free(tmp_ctx);
214 return LDB_ERR_NO_SUCH_OBJECT;
216 if (res->count != 1) {
217 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
218 GUID_string(tmp_ctx, guid));
219 talloc_free(tmp_ctx);
220 return LDB_ERR_OPERATIONS_ERROR;
223 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
225 talloc_free(tmp_ctx);
230 find a GUID given a DN.
232 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
234 const char *attrs[] = { NULL };
235 struct ldb_result *res;
236 TALLOC_CTX *tmp_ctx = talloc_new(module);
240 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
241 DSDB_FLAG_NEXT_MODULE |
242 DSDB_SEARCH_SHOW_RECYCLED |
243 DSDB_SEARCH_SHOW_EXTENDED_DN);
244 if (ret != LDB_SUCCESS) {
245 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
246 ldb_dn_get_linearized(dn));
247 talloc_free(tmp_ctx);
251 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
252 if (!NT_STATUS_IS_OK(status)) {
253 talloc_free(tmp_ctx);
254 return ldb_operr(ldb_module_get_ctx(module));
257 talloc_free(tmp_ctx);
262 a ldb_modify request operating on modules below the
265 int dsdb_module_modify(struct ldb_module *module,
266 const struct ldb_message *message,
269 struct ldb_request *mod_req;
271 struct ldb_context *ldb = ldb_module_get_ctx(module);
272 TALLOC_CTX *tmp_ctx = talloc_new(module);
273 struct ldb_result *res;
275 res = talloc_zero(tmp_ctx, struct ldb_result);
277 talloc_free(tmp_ctx);
278 return ldb_oom(ldb_module_get_ctx(module));
281 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
285 ldb_modify_default_callback,
287 LDB_REQ_SET_LOCATION(mod_req);
288 if (ret != LDB_SUCCESS) {
289 talloc_free(tmp_ctx);
293 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
294 if (ret != LDB_SUCCESS) {
295 talloc_free(tmp_ctx);
299 /* Run the new request */
300 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
301 ret = ldb_next_request(module, mod_req);
302 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
303 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
305 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
306 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
307 ret = ops->modify(module, mod_req);
309 if (ret == LDB_SUCCESS) {
310 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
313 talloc_free(tmp_ctx);
320 a ldb_rename request operating on modules below the
323 int dsdb_module_rename(struct ldb_module *module,
324 struct ldb_dn *olddn, struct ldb_dn *newdn,
327 struct ldb_request *req;
329 struct ldb_context *ldb = ldb_module_get_ctx(module);
330 TALLOC_CTX *tmp_ctx = talloc_new(module);
331 struct ldb_result *res;
333 res = talloc_zero(tmp_ctx, struct ldb_result);
335 talloc_free(tmp_ctx);
336 return ldb_oom(ldb_module_get_ctx(module));
339 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
344 ldb_modify_default_callback,
346 LDB_REQ_SET_LOCATION(req);
347 if (ret != LDB_SUCCESS) {
348 talloc_free(tmp_ctx);
352 ret = dsdb_request_add_controls(req, dsdb_flags);
353 if (ret != LDB_SUCCESS) {
354 talloc_free(tmp_ctx);
358 /* Run the new request */
359 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
360 ret = ldb_next_request(module, req);
361 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
362 ret = ldb_request(ldb_module_get_ctx(module), req);
364 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
365 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
366 ret = ops->rename(module, req);
368 if (ret == LDB_SUCCESS) {
369 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
372 talloc_free(tmp_ctx);
377 a ldb_add request operating on modules below the
380 int dsdb_module_add(struct ldb_module *module,
381 const struct ldb_message *message,
384 struct ldb_request *req;
386 struct ldb_context *ldb = ldb_module_get_ctx(module);
387 TALLOC_CTX *tmp_ctx = talloc_new(module);
388 struct ldb_result *res;
390 res = talloc_zero(tmp_ctx, struct ldb_result);
392 talloc_free(tmp_ctx);
393 return ldb_oom(ldb_module_get_ctx(module));
396 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
400 ldb_modify_default_callback,
402 LDB_REQ_SET_LOCATION(req);
403 if (ret != LDB_SUCCESS) {
404 talloc_free(tmp_ctx);
408 ret = dsdb_request_add_controls(req, dsdb_flags);
409 if (ret != LDB_SUCCESS) {
410 talloc_free(tmp_ctx);
414 /* Run the new request */
415 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
416 ret = ldb_next_request(module, req);
417 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
418 ret = ldb_request(ldb_module_get_ctx(module), req);
420 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
421 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
422 ret = ops->add(module, req);
424 if (ret == LDB_SUCCESS) {
425 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
428 talloc_free(tmp_ctx);
433 a ldb_delete request operating on modules below the
436 int dsdb_module_del(struct ldb_module *module,
440 struct ldb_request *req;
442 struct ldb_context *ldb = ldb_module_get_ctx(module);
443 TALLOC_CTX *tmp_ctx = talloc_new(module);
444 struct ldb_result *res;
446 res = talloc_zero(tmp_ctx, struct ldb_result);
448 talloc_free(tmp_ctx);
452 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
456 ldb_modify_default_callback,
458 LDB_REQ_SET_LOCATION(req);
459 if (ret != LDB_SUCCESS) {
460 talloc_free(tmp_ctx);
464 ret = dsdb_request_add_controls(req, dsdb_flags);
465 if (ret != LDB_SUCCESS) {
466 talloc_free(tmp_ctx);
470 /* Run the new request */
471 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
472 ret = ldb_next_request(module, req);
473 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
474 ret = ldb_request(ldb_module_get_ctx(module), req);
476 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
477 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
478 ret = ops->del(module, req);
480 if (ret == LDB_SUCCESS) {
481 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
484 talloc_free(tmp_ctx);
489 check if a single valued link has multiple non-deleted values
491 This is needed when we will be using the RELAX control to stop
492 ldb_tdb from checking single valued links
494 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
495 const struct ldb_message_element *el)
497 bool found_active = false;
500 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
501 el->num_values < 2) {
505 for (i=0; i<el->num_values; i++) {
506 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
508 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
517 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
518 struct GUID op_feature_guid, bool *feature_enabled)
521 struct ldb_context *ldb = ldb_module_get_ctx(module);
522 struct ldb_result *res;
523 struct ldb_dn *search_dn;
524 struct GUID search_guid;
525 const char *attrs[] = {"msDS-EnabledFeature", NULL};
528 struct ldb_message_element *el;
530 *feature_enabled = false;
532 tmp_ctx = talloc_new(ldb);
534 ret = ldb_search(ldb, tmp_ctx, &res,
535 scope, LDB_SCOPE_BASE, attrs,
537 if (ret != LDB_SUCCESS) {
538 ldb_asprintf_errstring(ldb,
539 "Could no find the scope object - dn: %s\n",
540 ldb_dn_get_linearized(scope));
541 talloc_free(tmp_ctx);
542 return LDB_ERR_OPERATIONS_ERROR;
544 if (res->msgs[0]->num_elements > 0) {
546 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
548 attrs[0] = "msDS-OptionalFeatureGUID";
550 for (i=0; i<el->num_values; i++) {
551 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
553 ret = ldb_search(ldb, tmp_ctx, &res,
554 search_dn, LDB_SCOPE_BASE, attrs,
556 if (ret != LDB_SUCCESS) {
557 ldb_asprintf_errstring(ldb,
558 "Could no find object dn: %s\n",
559 ldb_dn_get_linearized(search_dn));
560 talloc_free(tmp_ctx);
561 return LDB_ERR_OPERATIONS_ERROR;
564 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
566 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
567 *feature_enabled = true;
572 talloc_free(tmp_ctx);
577 find a 'reference' DN that points at another object
578 (eg. serverReference, rIDManagerReference etc)
580 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
581 const char *attribute, struct ldb_dn **dn)
583 const char *attrs[2];
584 struct ldb_result *res;
587 attrs[0] = attribute;
590 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
591 DSDB_FLAG_NEXT_MODULE);
592 if (ret != LDB_SUCCESS) {
596 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
597 mem_ctx, res->msgs[0], attribute);
599 ldb_reset_err_string(ldb_module_get_ctx(module));
601 return LDB_ERR_NO_SUCH_ATTRIBUTE;
609 find the RID Manager$ DN via the rIDManagerReference attribute in the
612 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
614 return dsdb_module_reference_dn(module, mem_ctx,
615 ldb_get_default_basedn(ldb_module_get_ctx(module)),
616 "rIDManagerReference", dn);
620 used to chain to the callers callback
622 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
624 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
626 talloc_steal(up_req, req);
627 return up_req->callback(up_req, ares);
631 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
632 object for a partition
634 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
635 uint64_t *uSN, uint64_t *urgent_uSN)
637 struct ldb_context *ldb = ldb_module_get_ctx(module);
638 struct ldb_request *req;
640 TALLOC_CTX *tmp_ctx = talloc_new(module);
641 struct dsdb_control_current_partition *p_ctrl;
642 struct ldb_result *res;
644 res = talloc_zero(tmp_ctx, struct ldb_result);
646 talloc_free(tmp_ctx);
647 return ldb_module_oom(module);
650 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
651 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
655 res, ldb_search_default_callback,
657 LDB_REQ_SET_LOCATION(req);
658 if (ret != LDB_SUCCESS) {
659 talloc_free(tmp_ctx);
663 p_ctrl = talloc(req, struct dsdb_control_current_partition);
664 if (p_ctrl == NULL) {
665 talloc_free(tmp_ctx);
666 return ldb_module_oom(module);
668 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
672 ret = ldb_request_add_control(req,
673 DSDB_CONTROL_CURRENT_PARTITION_OID,
675 if (ret != LDB_SUCCESS) {
676 talloc_free(tmp_ctx);
680 /* Run the new request */
681 ret = ldb_next_request(module, req);
683 if (ret == LDB_SUCCESS) {
684 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
687 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
688 /* it hasn't been created yet, which means
689 an implicit value of zero */
691 talloc_free(tmp_ctx);
692 ldb_reset_err_string(ldb);
696 if (ret != LDB_SUCCESS) {
697 talloc_free(tmp_ctx);
701 if (res->count != 1) {
707 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
709 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
713 talloc_free(tmp_ctx);
719 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
722 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
723 uint64_t uSN, uint64_t urgent_uSN)
725 struct ldb_context *ldb = ldb_module_get_ctx(module);
726 struct ldb_request *req;
727 struct ldb_message *msg;
728 struct dsdb_control_current_partition *p_ctrl;
730 struct ldb_result *res;
732 msg = ldb_msg_new(module);
734 return ldb_module_oom(module);
737 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
738 if (msg->dn == NULL) {
740 return ldb_operr(ldb_module_get_ctx(module));
743 res = talloc_zero(msg, struct ldb_result);
746 return ldb_module_oom(module);
749 ret = ldb_msg_add_fmt(msg, "uSNHighest", "%llu", (unsigned long long)uSN);
750 if (ret != LDB_SUCCESS) {
754 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
756 /* urgent_uSN is optional so may not be stored */
758 ret = ldb_msg_add_fmt(msg, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN);
759 if (ret != LDB_SUCCESS) {
763 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
767 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
768 if (p_ctrl == NULL) {
772 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
774 ret = ldb_build_mod_req(&req, ldb, msg,
778 ldb_modify_default_callback,
780 LDB_REQ_SET_LOCATION(req);
782 if (ret != LDB_SUCCESS) {
787 ret = ldb_request_add_control(req,
788 DSDB_CONTROL_CURRENT_PARTITION_OID,
790 if (ret != LDB_SUCCESS) {
795 /* Run the new request */
796 ret = ldb_next_request(module, req);
798 if (ret == LDB_SUCCESS) {
799 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
801 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
802 ret = ldb_build_add_req(&req, ldb, msg,
806 ldb_modify_default_callback,
808 LDB_REQ_SET_LOCATION(req);
817 bool dsdb_module_am_system(struct ldb_module *module)
819 struct ldb_context *ldb = ldb_module_get_ctx(module);
820 struct auth_session_info *session_info
821 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
822 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
825 bool dsdb_module_am_administrator(struct ldb_module *module)
827 struct ldb_context *ldb = ldb_module_get_ctx(module);
828 struct auth_session_info *session_info
829 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
830 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
834 check if the recyclebin is enabled
836 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
838 struct ldb_context *ldb = ldb_module_get_ctx(module);
839 struct ldb_dn *partitions_dn;
840 struct GUID recyclebin_guid;
843 partitions_dn = samdb_partitions_dn(ldb, module);
845 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
847 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
848 if (ret != LDB_SUCCESS) {
849 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
850 talloc_free(partitions_dn);
851 return LDB_ERR_UNWILLING_TO_PERFORM;
854 talloc_free(partitions_dn);
858 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
859 struct ldb_message *msg,
861 const int32_t *old_val,
862 const int32_t *new_val)
864 struct ldb_message_element *el;
869 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
870 if (ret != LDB_SUCCESS) {
874 el->values = talloc_array(msg, struct ldb_val, el->num_values);
876 return ldb_module_oom(module);
878 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
880 return ldb_module_oom(module);
882 *el->values = data_blob_string_const(vstring);
886 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
887 if (ret != LDB_SUCCESS) {
891 el->values = talloc_array(msg, struct ldb_val, el->num_values);
893 return ldb_module_oom(module);
895 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
897 return ldb_module_oom(module);
899 *el->values = data_blob_string_const(vstring);
905 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
906 struct ldb_message *msg,
908 const uint32_t *old_val,
909 const uint32_t *new_val)
911 return dsdb_msg_constrainted_update_int32(module, msg, attr,
912 (const int32_t *)old_val,
913 (const int32_t *)new_val);
916 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
917 struct ldb_message *msg,
919 const int64_t *old_val,
920 const int64_t *new_val)
922 struct ldb_message_element *el;
927 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
928 if (ret != LDB_SUCCESS) {
932 el->values = talloc_array(msg, struct ldb_val, el->num_values);
934 return ldb_module_oom(module);
936 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
938 return ldb_module_oom(module);
940 *el->values = data_blob_string_const(vstring);
944 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
945 if (ret != LDB_SUCCESS) {
949 el->values = talloc_array(msg, struct ldb_val, el->num_values);
951 return ldb_module_oom(module);
953 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
955 return ldb_module_oom(module);
957 *el->values = data_blob_string_const(vstring);
963 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
964 struct ldb_message *msg,
966 const uint64_t *old_val,
967 const uint64_t *new_val)
969 return dsdb_msg_constrainted_update_int64(module, msg, attr,
970 (const int64_t *)old_val,
971 (const int64_t *)new_val);
975 update an int32 attribute safely via a constrained delete/add
977 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
980 const int32_t *old_val,
981 const int32_t *new_val)
983 struct ldb_message *msg;
986 msg = ldb_msg_new(module);
989 ret = dsdb_msg_constrainted_update_int32(module,
993 if (ret != LDB_SUCCESS) {
998 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1003 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1006 const uint32_t *old_val,
1007 const uint32_t *new_val)
1009 return dsdb_module_constrainted_update_int32(module, dn, attr,
1010 (const int32_t *)old_val,
1011 (const int32_t *)new_val);
1015 update an int64 attribute safely via a constrained delete/add
1017 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1020 const int64_t *old_val,
1021 const int64_t *new_val)
1023 struct ldb_message *msg;
1026 msg = ldb_msg_new(module);
1029 ret = dsdb_msg_constrainted_update_int64(module,
1033 if (ret != LDB_SUCCESS) {
1038 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1043 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1046 const uint64_t *old_val,
1047 const uint64_t *new_val)
1049 return dsdb_module_constrainted_update_int64(module, dn, attr,
1050 (const int64_t *)old_val,
1051 (const int64_t *)new_val);
1055 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1056 TALLOC_CTX *mem_ctx)
1059 struct ldb_dn *new_dn;
1060 struct ldb_context *ldb = ldb_module_get_ctx(module);
1061 static const char *attrs[] = { "dsHeuristics", NULL };
1062 struct ldb_result *res;
1064 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1065 if (!ldb_dn_add_child_fmt(new_dn,
1066 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1067 talloc_free(new_dn);
1070 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1073 DSDB_FLAG_NEXT_MODULE);
1074 if (ret == LDB_SUCCESS && res->count == 1) {
1075 talloc_free(new_dn);
1076 return ldb_msg_find_ldb_val(res->msgs[0],
1079 talloc_free(new_dn);
1083 bool dsdb_block_anonymous_ops(struct ldb_module *module,
1084 TALLOC_CTX *mem_ctx)
1086 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1088 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1090 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1092 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1098 talloc_free(tmp_ctx);
1103 show the chain of requests, useful for debugging async requests
1105 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1109 while (req && req->handle) {
1110 DEBUG(level,("req[%u] %p : %s\n", i++, req, ldb_req_location(req)));
1111 req = req->handle->parent;