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 "libcli/security/session.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);
114 search for attrs in the modules below
116 int dsdb_module_search(struct ldb_module *module,
118 struct ldb_result **_res,
119 struct ldb_dn *basedn, enum ldb_scope scope,
120 const char * const *attrs,
122 struct ldb_request *parent,
123 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
126 struct ldb_request *req;
128 struct ldb_result *res;
132 tmp_ctx = talloc_new(mem_ctx);
135 va_start(ap, format);
136 expression = talloc_vasprintf(tmp_ctx, format, ap);
140 talloc_free(tmp_ctx);
141 return ldb_oom(ldb_module_get_ctx(module));
147 res = talloc_zero(tmp_ctx, struct ldb_result);
149 talloc_free(tmp_ctx);
150 return ldb_oom(ldb_module_get_ctx(module));
153 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
160 ldb_search_default_callback,
162 LDB_REQ_SET_LOCATION(req);
163 if (ret != LDB_SUCCESS) {
164 talloc_free(tmp_ctx);
168 ret = dsdb_request_add_controls(req, dsdb_flags);
169 if (ret != LDB_SUCCESS) {
170 talloc_free(tmp_ctx);
174 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
175 ldb_req_mark_trusted(req);
178 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
179 ret = ldb_next_request(module, req);
180 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
181 ret = ldb_request(ldb_module_get_ctx(module), req);
183 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
184 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
185 ret = ops->search(module, req);
187 if (ret == LDB_SUCCESS) {
188 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
192 if (ret == LDB_SUCCESS) {
193 *_res = talloc_steal(mem_ctx, res);
195 talloc_free(tmp_ctx);
200 find a DN given a GUID. This searches across all partitions
202 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
203 const struct GUID *guid, struct ldb_dn **dn,
204 struct ldb_request *parent)
206 struct ldb_result *res;
207 const char *attrs[] = { NULL };
208 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
211 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
213 DSDB_FLAG_NEXT_MODULE |
214 DSDB_SEARCH_SHOW_RECYCLED |
215 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
216 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
218 "objectGUID=%s", GUID_string(tmp_ctx, guid));
219 if (ret != LDB_SUCCESS) {
220 talloc_free(tmp_ctx);
223 if (res->count == 0) {
224 talloc_free(tmp_ctx);
225 return LDB_ERR_NO_SUCH_OBJECT;
227 if (res->count != 1) {
228 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
229 GUID_string(tmp_ctx, guid));
230 talloc_free(tmp_ctx);
231 return LDB_ERR_OPERATIONS_ERROR;
234 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
236 talloc_free(tmp_ctx);
241 find a GUID given a DN.
243 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
244 struct ldb_request *parent)
246 const char *attrs[] = { NULL };
247 struct ldb_result *res;
248 TALLOC_CTX *tmp_ctx = talloc_new(module);
252 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
253 DSDB_FLAG_NEXT_MODULE |
254 DSDB_SEARCH_SHOW_RECYCLED |
255 DSDB_SEARCH_SHOW_EXTENDED_DN,
257 if (ret != LDB_SUCCESS) {
258 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
259 ldb_dn_get_linearized(dn));
260 talloc_free(tmp_ctx);
264 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
265 if (!NT_STATUS_IS_OK(status)) {
266 talloc_free(tmp_ctx);
267 return ldb_operr(ldb_module_get_ctx(module));
270 talloc_free(tmp_ctx);
275 a ldb_modify request operating on modules below the
278 int dsdb_module_modify(struct ldb_module *module,
279 const struct ldb_message *message,
281 struct ldb_request *parent)
283 struct ldb_request *mod_req;
285 struct ldb_context *ldb = ldb_module_get_ctx(module);
286 TALLOC_CTX *tmp_ctx = talloc_new(module);
287 struct ldb_result *res;
289 res = talloc_zero(tmp_ctx, struct ldb_result);
291 talloc_free(tmp_ctx);
292 return ldb_oom(ldb_module_get_ctx(module));
295 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
299 ldb_modify_default_callback,
301 LDB_REQ_SET_LOCATION(mod_req);
302 if (ret != LDB_SUCCESS) {
303 talloc_free(tmp_ctx);
307 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
308 if (ret != LDB_SUCCESS) {
309 talloc_free(tmp_ctx);
313 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
314 ldb_req_mark_trusted(mod_req);
317 /* Run the new request */
318 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
319 ret = ldb_next_request(module, mod_req);
320 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
321 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
323 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
324 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
325 ret = ops->modify(module, mod_req);
327 if (ret == LDB_SUCCESS) {
328 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
331 talloc_free(tmp_ctx);
338 a ldb_rename request operating on modules below the
341 int dsdb_module_rename(struct ldb_module *module,
342 struct ldb_dn *olddn, struct ldb_dn *newdn,
344 struct ldb_request *parent)
346 struct ldb_request *req;
348 struct ldb_context *ldb = ldb_module_get_ctx(module);
349 TALLOC_CTX *tmp_ctx = talloc_new(module);
350 struct ldb_result *res;
352 res = talloc_zero(tmp_ctx, struct ldb_result);
354 talloc_free(tmp_ctx);
355 return ldb_oom(ldb_module_get_ctx(module));
358 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
363 ldb_modify_default_callback,
365 LDB_REQ_SET_LOCATION(req);
366 if (ret != LDB_SUCCESS) {
367 talloc_free(tmp_ctx);
371 ret = dsdb_request_add_controls(req, dsdb_flags);
372 if (ret != LDB_SUCCESS) {
373 talloc_free(tmp_ctx);
377 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
378 ldb_req_mark_trusted(req);
381 /* Run the new request */
382 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
383 ret = ldb_next_request(module, req);
384 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
385 ret = ldb_request(ldb_module_get_ctx(module), req);
387 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
388 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
389 ret = ops->rename(module, req);
391 if (ret == LDB_SUCCESS) {
392 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
395 talloc_free(tmp_ctx);
400 a ldb_add request operating on modules below the
403 int dsdb_module_add(struct ldb_module *module,
404 const struct ldb_message *message,
406 struct ldb_request *parent)
408 struct ldb_request *req;
410 struct ldb_context *ldb = ldb_module_get_ctx(module);
411 TALLOC_CTX *tmp_ctx = talloc_new(module);
412 struct ldb_result *res;
414 res = talloc_zero(tmp_ctx, struct ldb_result);
416 talloc_free(tmp_ctx);
417 return ldb_oom(ldb_module_get_ctx(module));
420 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
424 ldb_modify_default_callback,
426 LDB_REQ_SET_LOCATION(req);
427 if (ret != LDB_SUCCESS) {
428 talloc_free(tmp_ctx);
432 ret = dsdb_request_add_controls(req, dsdb_flags);
433 if (ret != LDB_SUCCESS) {
434 talloc_free(tmp_ctx);
438 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
439 ldb_req_mark_trusted(req);
442 /* Run the new request */
443 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
444 ret = ldb_next_request(module, req);
445 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
446 ret = ldb_request(ldb_module_get_ctx(module), req);
448 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
449 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
450 ret = ops->add(module, req);
452 if (ret == LDB_SUCCESS) {
453 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
456 talloc_free(tmp_ctx);
461 a ldb_delete request operating on modules below the
464 int dsdb_module_del(struct ldb_module *module,
467 struct ldb_request *parent)
469 struct ldb_request *req;
471 struct ldb_context *ldb = ldb_module_get_ctx(module);
472 TALLOC_CTX *tmp_ctx = talloc_new(module);
473 struct ldb_result *res;
475 res = talloc_zero(tmp_ctx, struct ldb_result);
477 talloc_free(tmp_ctx);
481 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
485 ldb_modify_default_callback,
487 LDB_REQ_SET_LOCATION(req);
488 if (ret != LDB_SUCCESS) {
489 talloc_free(tmp_ctx);
493 ret = dsdb_request_add_controls(req, dsdb_flags);
494 if (ret != LDB_SUCCESS) {
495 talloc_free(tmp_ctx);
499 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
500 ldb_req_mark_trusted(req);
503 /* Run the new request */
504 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
505 ret = ldb_next_request(module, req);
506 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
507 ret = ldb_request(ldb_module_get_ctx(module), req);
509 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
510 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
511 ret = ops->del(module, req);
513 if (ret == LDB_SUCCESS) {
514 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
517 talloc_free(tmp_ctx);
522 check if a single valued link has multiple non-deleted values
524 This is needed when we will be using the RELAX control to stop
525 ldb_tdb from checking single valued links
527 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
528 const struct ldb_message_element *el)
530 bool found_active = false;
533 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
534 el->num_values < 2) {
538 for (i=0; i<el->num_values; i++) {
539 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
541 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
550 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
551 struct GUID op_feature_guid, bool *feature_enabled)
554 struct ldb_context *ldb = ldb_module_get_ctx(module);
555 struct ldb_result *res;
556 struct ldb_dn *search_dn;
557 struct GUID search_guid;
558 const char *attrs[] = {"msDS-EnabledFeature", NULL};
561 struct ldb_message_element *el;
563 *feature_enabled = false;
565 tmp_ctx = talloc_new(ldb);
567 ret = ldb_search(ldb, tmp_ctx, &res,
568 scope, LDB_SCOPE_BASE, attrs,
570 if (ret != LDB_SUCCESS) {
571 ldb_asprintf_errstring(ldb,
572 "Could no find the scope object - dn: %s\n",
573 ldb_dn_get_linearized(scope));
574 talloc_free(tmp_ctx);
575 return LDB_ERR_OPERATIONS_ERROR;
577 if (res->msgs[0]->num_elements > 0) {
579 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
581 attrs[0] = "msDS-OptionalFeatureGUID";
583 for (i=0; i<el->num_values; i++) {
584 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
586 ret = ldb_search(ldb, tmp_ctx, &res,
587 search_dn, LDB_SCOPE_BASE, attrs,
589 if (ret != LDB_SUCCESS) {
590 ldb_asprintf_errstring(ldb,
591 "Could no find object dn: %s\n",
592 ldb_dn_get_linearized(search_dn));
593 talloc_free(tmp_ctx);
594 return LDB_ERR_OPERATIONS_ERROR;
597 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
599 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
600 *feature_enabled = true;
605 talloc_free(tmp_ctx);
610 find a 'reference' DN that points at another object
611 (eg. serverReference, rIDManagerReference etc)
613 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
614 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
616 const char *attrs[2];
617 struct ldb_result *res;
620 attrs[0] = attribute;
623 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
624 DSDB_FLAG_NEXT_MODULE, parent);
625 if (ret != LDB_SUCCESS) {
629 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
630 mem_ctx, res->msgs[0], attribute);
632 ldb_reset_err_string(ldb_module_get_ctx(module));
634 return LDB_ERR_NO_SUCH_ATTRIBUTE;
642 find the RID Manager$ DN via the rIDManagerReference attribute in the
645 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
646 struct ldb_request *parent)
648 return dsdb_module_reference_dn(module, mem_ctx,
649 ldb_get_default_basedn(ldb_module_get_ctx(module)),
650 "rIDManagerReference", dn, parent);
654 used to chain to the callers callback
656 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
658 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
660 talloc_steal(up_req, req);
661 return up_req->callback(up_req, ares);
665 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
666 object for a partition
668 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
669 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
671 struct ldb_context *ldb = ldb_module_get_ctx(module);
672 struct ldb_request *req;
674 TALLOC_CTX *tmp_ctx = talloc_new(module);
675 struct dsdb_control_current_partition *p_ctrl;
676 struct ldb_result *res;
678 res = talloc_zero(tmp_ctx, struct ldb_result);
680 talloc_free(tmp_ctx);
681 return ldb_module_oom(module);
684 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
685 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
689 res, ldb_search_default_callback,
691 LDB_REQ_SET_LOCATION(req);
692 if (ret != LDB_SUCCESS) {
693 talloc_free(tmp_ctx);
697 p_ctrl = talloc(req, struct dsdb_control_current_partition);
698 if (p_ctrl == NULL) {
699 talloc_free(tmp_ctx);
700 return ldb_module_oom(module);
702 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
706 ret = ldb_request_add_control(req,
707 DSDB_CONTROL_CURRENT_PARTITION_OID,
709 if (ret != LDB_SUCCESS) {
710 talloc_free(tmp_ctx);
714 /* Run the new request */
715 ret = ldb_next_request(module, req);
717 if (ret == LDB_SUCCESS) {
718 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
721 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
722 /* it hasn't been created yet, which means
723 an implicit value of zero */
725 talloc_free(tmp_ctx);
726 ldb_reset_err_string(ldb);
730 if (ret != LDB_SUCCESS) {
731 talloc_free(tmp_ctx);
735 if (res->count != 1) {
741 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
743 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
747 talloc_free(tmp_ctx);
753 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
756 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
757 uint64_t uSN, uint64_t urgent_uSN,
758 struct ldb_request *parent)
760 struct ldb_context *ldb = ldb_module_get_ctx(module);
761 struct ldb_request *req;
762 struct ldb_message *msg;
763 struct dsdb_control_current_partition *p_ctrl;
765 struct ldb_result *res;
767 msg = ldb_msg_new(module);
769 return ldb_module_oom(module);
772 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
773 if (msg->dn == NULL) {
775 return ldb_operr(ldb_module_get_ctx(module));
778 res = talloc_zero(msg, struct ldb_result);
781 return ldb_module_oom(module);
784 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
785 if (ret != LDB_SUCCESS) {
789 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
791 /* urgent_uSN is optional so may not be stored */
793 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
795 if (ret != LDB_SUCCESS) {
799 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
803 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
804 if (p_ctrl == NULL) {
808 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
810 ret = ldb_build_mod_req(&req, ldb, msg,
814 ldb_modify_default_callback,
816 LDB_REQ_SET_LOCATION(req);
818 if (ret != LDB_SUCCESS) {
823 ret = ldb_request_add_control(req,
824 DSDB_CONTROL_CURRENT_PARTITION_OID,
826 if (ret != LDB_SUCCESS) {
831 /* Run the new request */
832 ret = ldb_next_request(module, req);
834 if (ret == LDB_SUCCESS) {
835 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
837 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
838 ret = ldb_build_add_req(&req, ldb, msg,
842 ldb_modify_default_callback,
844 LDB_REQ_SET_LOCATION(req);
853 bool dsdb_module_am_system(struct ldb_module *module)
855 struct ldb_context *ldb = ldb_module_get_ctx(module);
856 struct auth_session_info *session_info
857 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
858 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
861 bool dsdb_module_am_administrator(struct ldb_module *module)
863 struct ldb_context *ldb = ldb_module_get_ctx(module);
864 struct auth_session_info *session_info
865 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
866 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
870 check if the recyclebin is enabled
872 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
874 struct ldb_context *ldb = ldb_module_get_ctx(module);
875 struct ldb_dn *partitions_dn;
876 struct GUID recyclebin_guid;
879 partitions_dn = samdb_partitions_dn(ldb, module);
881 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
883 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
884 if (ret != LDB_SUCCESS) {
885 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
886 talloc_free(partitions_dn);
887 return LDB_ERR_UNWILLING_TO_PERFORM;
890 talloc_free(partitions_dn);
894 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
895 struct ldb_message *msg,
897 const int32_t *old_val,
898 const int32_t *new_val)
900 struct ldb_message_element *el;
905 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
906 if (ret != LDB_SUCCESS) {
910 el->values = talloc_array(msg, struct ldb_val, el->num_values);
912 return ldb_module_oom(module);
914 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
916 return ldb_module_oom(module);
918 *el->values = data_blob_string_const(vstring);
922 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
923 if (ret != LDB_SUCCESS) {
927 el->values = talloc_array(msg, struct ldb_val, el->num_values);
929 return ldb_module_oom(module);
931 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
933 return ldb_module_oom(module);
935 *el->values = data_blob_string_const(vstring);
941 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
942 struct ldb_message *msg,
944 const uint32_t *old_val,
945 const uint32_t *new_val)
947 return dsdb_msg_constrainted_update_int32(module, msg, attr,
948 (const int32_t *)old_val,
949 (const int32_t *)new_val);
952 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
953 struct ldb_message *msg,
955 const int64_t *old_val,
956 const int64_t *new_val)
958 struct ldb_message_element *el;
963 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
964 if (ret != LDB_SUCCESS) {
968 el->values = talloc_array(msg, struct ldb_val, el->num_values);
970 return ldb_module_oom(module);
972 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
974 return ldb_module_oom(module);
976 *el->values = data_blob_string_const(vstring);
980 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &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, "%lld", (long long)*new_val);
991 return ldb_module_oom(module);
993 *el->values = data_blob_string_const(vstring);
999 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1000 struct ldb_message *msg,
1002 const uint64_t *old_val,
1003 const uint64_t *new_val)
1005 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1006 (const int64_t *)old_val,
1007 (const int64_t *)new_val);
1011 update an int32 attribute safely via a constrained delete/add
1013 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1016 const int32_t *old_val,
1017 const int32_t *new_val,
1018 struct ldb_request *parent)
1020 struct ldb_message *msg;
1023 msg = ldb_msg_new(module);
1026 ret = dsdb_msg_constrainted_update_int32(module,
1030 if (ret != LDB_SUCCESS) {
1035 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1040 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1043 const uint32_t *old_val,
1044 const uint32_t *new_val,
1045 struct ldb_request *parent)
1047 return dsdb_module_constrainted_update_int32(module, dn, attr,
1048 (const int32_t *)old_val,
1049 (const int32_t *)new_val, parent);
1053 update an int64 attribute safely via a constrained delete/add
1055 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1058 const int64_t *old_val,
1059 const int64_t *new_val,
1060 struct ldb_request *parent)
1062 struct ldb_message *msg;
1065 msg = ldb_msg_new(module);
1068 ret = dsdb_msg_constrainted_update_int64(module,
1072 if (ret != LDB_SUCCESS) {
1077 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1082 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1085 const uint64_t *old_val,
1086 const uint64_t *new_val,
1087 struct ldb_request *parent)
1089 return dsdb_module_constrainted_update_int64(module, dn, attr,
1090 (const int64_t *)old_val,
1091 (const int64_t *)new_val,
1096 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1097 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1100 struct ldb_dn *new_dn;
1101 struct ldb_context *ldb = ldb_module_get_ctx(module);
1102 static const char *attrs[] = { "dSHeuristics", NULL };
1103 struct ldb_result *res;
1105 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1106 if (!ldb_dn_add_child_fmt(new_dn,
1107 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1108 talloc_free(new_dn);
1111 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1114 DSDB_FLAG_NEXT_MODULE,
1116 if (ret == LDB_SUCCESS && res->count == 1) {
1117 talloc_free(new_dn);
1118 return ldb_msg_find_ldb_val(res->msgs[0],
1121 talloc_free(new_dn);
1125 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1127 TALLOC_CTX *tmp_ctx = talloc_new(module);
1129 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1131 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1133 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1139 talloc_free(tmp_ctx);
1143 bool dsdb_user_password_support(struct ldb_module *module,
1144 TALLOC_CTX *mem_ctx,
1145 struct ldb_request *parent)
1147 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1149 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1152 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1154 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1155 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1161 talloc_free(tmp_ctx);
1166 show the chain of requests, useful for debugging async requests
1168 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1170 char *s = ldb_module_call_chain(req, req);
1171 DEBUG(level, ("%s\n", s));
1176 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1177 * performing a modify operation.
1179 * In order that the constraint checking by the "objectclass_attrs" LDB module
1180 * does work properly, the change request should remain similar or only be
1181 * enhanced (no other modifications as deletions, variations).
1183 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1184 const char *attr_name,
1185 enum ldb_request_type operation)
1187 struct ldb_message_element *el = NULL;
1190 /* We've to walk over all modification entries and consider the last
1191 * non-delete one which belongs to "attr_name".
1193 * If "el" is NULL afterwards then that means there was no interesting
1195 for (i = 0; i < msg->num_elements; i++) {
1196 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1197 if ((operation == LDB_MODIFY) &&
1198 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1199 == LDB_FLAG_MOD_DELETE)) {
1202 el = &msg->elements[i];