Revert "s4:prefer "samdb_*_dn" basedn calls over the "ldb_get_*_dn" functions"
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / util.c
blobfe0ff7510ba88535b923726957a3e76b5442f02f
1 /*
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/>.
22 #include "includes.h"
23 #include "ldb.h"
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"
28 #include "util.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,
35 TALLOC_CTX *mem_ctx,
36 struct ldb_result **_res,
37 struct ldb_dn *basedn,
38 const char * const *attrs,
39 uint32_t dsdb_flags)
41 int ret;
42 struct ldb_request *req;
43 TALLOC_CTX *tmp_ctx;
44 struct ldb_result *res;
46 tmp_ctx = talloc_new(mem_ctx);
48 res = talloc_zero(tmp_ctx, struct ldb_result);
49 if (!res) {
50 return LDB_ERR_OPERATIONS_ERROR;
53 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
54 basedn,
55 LDB_SCOPE_BASE,
56 NULL,
57 attrs,
58 NULL,
59 res,
60 ldb_search_default_callback,
61 NULL);
62 if (ret != LDB_SUCCESS) {
63 talloc_free(tmp_ctx);
64 return ret;
67 ret = dsdb_request_add_controls(req, dsdb_flags);
68 if (ret != LDB_SUCCESS) {
69 talloc_free(tmp_ctx);
70 return ret;
73 ret = ldb_next_request(module, req);
74 if (ret == LDB_SUCCESS) {
75 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
78 if (ret != LDB_SUCCESS) {
79 talloc_free(tmp_ctx);
80 return ret;
83 if (res->count != 1) {
84 /* we may be reading a DB that does not have the 'check base on search' option... */
85 ret = LDB_ERR_NO_SUCH_OBJECT;
86 ldb_asprintf_errstring(ldb_module_get_ctx(module),
87 "dsdb_module_search_dn: did not find base dn %s (%d results)",
88 ldb_dn_get_linearized(basedn), res->count);
89 } else {
90 *_res = talloc_steal(mem_ctx, res);
92 talloc_free(tmp_ctx);
93 return ret;
97 search for attrs in the modules below
99 int dsdb_module_search(struct ldb_module *module,
100 TALLOC_CTX *mem_ctx,
101 struct ldb_result **_res,
102 struct ldb_dn *basedn, enum ldb_scope scope,
103 const char * const *attrs,
104 int dsdb_flags,
105 const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
107 int ret;
108 struct ldb_request *req;
109 TALLOC_CTX *tmp_ctx;
110 struct ldb_result *res;
111 va_list ap;
112 char *expression;
114 tmp_ctx = talloc_new(mem_ctx);
116 va_start(ap, format);
117 expression = talloc_vasprintf(tmp_ctx, format, ap);
118 va_end(ap);
120 res = talloc_zero(tmp_ctx, struct ldb_result);
121 if (!res) {
122 return LDB_ERR_OPERATIONS_ERROR;
125 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
126 basedn,
127 scope,
128 expression,
129 attrs,
130 NULL,
131 res,
132 ldb_search_default_callback,
133 NULL);
134 if (ret != LDB_SUCCESS) {
135 talloc_free(tmp_ctx);
136 return ret;
139 ret = dsdb_request_add_controls(req, dsdb_flags);
140 if (ret != LDB_SUCCESS) {
141 talloc_free(tmp_ctx);
142 return ret;
145 if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
146 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
147 ret = ops->search(module, req);
148 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
149 ret = ldb_request(ldb_module_get_ctx(module), req);
150 } else {
151 ret = ldb_next_request(module, req);
153 if (ret == LDB_SUCCESS) {
154 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
157 talloc_free(req);
158 if (ret == LDB_SUCCESS) {
159 *_res = talloc_steal(mem_ctx, res);
161 talloc_free(tmp_ctx);
162 return ret;
166 find a DN given a GUID. This searches across all partitions
168 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
169 const struct GUID *guid, struct ldb_dn **dn)
171 struct ldb_result *res;
172 const char *attrs[] = { NULL };
173 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
174 int ret;
176 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
177 attrs,
178 DSDB_SEARCH_SHOW_DELETED |
179 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
180 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
181 "objectGUID=%s", GUID_string(tmp_ctx, guid));
182 if (ret != LDB_SUCCESS) {
183 talloc_free(tmp_ctx);
184 return ret;
186 if (res->count == 0) {
187 talloc_free(tmp_ctx);
188 return LDB_ERR_NO_SUCH_OBJECT;
190 if (res->count != 1) {
191 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
192 GUID_string(tmp_ctx, guid));
193 talloc_free(tmp_ctx);
194 return LDB_ERR_OPERATIONS_ERROR;
197 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
199 talloc_free(tmp_ctx);
200 return LDB_SUCCESS;
204 find a GUID given a DN.
206 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
208 const char *attrs[] = { NULL };
209 struct ldb_result *res;
210 TALLOC_CTX *tmp_ctx = talloc_new(module);
211 int ret;
212 NTSTATUS status;
214 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
215 DSDB_SEARCH_SHOW_DELETED|
216 DSDB_SEARCH_SHOW_EXTENDED_DN);
217 if (ret != LDB_SUCCESS) {
218 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
219 ldb_dn_get_linearized(dn));
220 talloc_free(tmp_ctx);
221 return ret;
224 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
225 if (!NT_STATUS_IS_OK(status)) {
226 talloc_free(tmp_ctx);
227 return LDB_ERR_OPERATIONS_ERROR;
230 talloc_free(tmp_ctx);
231 return LDB_SUCCESS;
235 a ldb_modify request operating on modules below the
236 current module
238 int dsdb_module_modify(struct ldb_module *module,
239 const struct ldb_message *message,
240 uint32_t dsdb_flags)
242 struct ldb_request *mod_req;
243 int ret;
244 struct ldb_context *ldb = ldb_module_get_ctx(module);
245 TALLOC_CTX *tmp_ctx = talloc_new(module);
247 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
248 message,
249 NULL,
250 NULL,
251 ldb_op_default_callback,
252 NULL);
253 if (ret != LDB_SUCCESS) {
254 talloc_free(tmp_ctx);
255 return ret;
258 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
259 if (ret != LDB_SUCCESS) {
260 talloc_free(tmp_ctx);
261 return ret;
264 /* Run the new request */
265 if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
266 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
267 ret = ops->modify(module, mod_req);
268 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
269 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
270 } else {
271 ret = ldb_next_request(module, mod_req);
273 if (ret == LDB_SUCCESS) {
274 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
277 talloc_free(tmp_ctx);
278 return ret;
284 a ldb_rename request operating on modules below the
285 current module
287 int dsdb_module_rename(struct ldb_module *module,
288 struct ldb_dn *olddn, struct ldb_dn *newdn,
289 uint32_t dsdb_flags)
291 struct ldb_request *req;
292 int ret;
293 struct ldb_context *ldb = ldb_module_get_ctx(module);
294 TALLOC_CTX *tmp_ctx = talloc_new(module);
296 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
297 olddn,
298 newdn,
299 NULL,
300 NULL,
301 ldb_op_default_callback,
302 NULL);
303 if (ret != LDB_SUCCESS) {
304 talloc_free(tmp_ctx);
305 return ret;
308 ret = dsdb_request_add_controls(req, dsdb_flags);
309 if (ret != LDB_SUCCESS) {
310 talloc_free(tmp_ctx);
311 return ret;
314 /* Run the new request */
315 if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
316 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
317 ret = ops->rename(module, req);
318 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
319 ret = ldb_request(ldb_module_get_ctx(module), req);
320 } else {
321 ret = ldb_next_request(module, req);
323 if (ret == LDB_SUCCESS) {
324 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
327 talloc_free(tmp_ctx);
328 return ret;
332 a ldb_add request operating on modules below the
333 current module
335 int dsdb_module_add(struct ldb_module *module,
336 const struct ldb_message *message,
337 uint32_t dsdb_flags)
339 struct ldb_request *req;
340 int ret;
341 struct ldb_context *ldb = ldb_module_get_ctx(module);
342 TALLOC_CTX *tmp_ctx = talloc_new(module);
344 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
345 message,
346 NULL,
347 NULL,
348 ldb_op_default_callback,
349 NULL);
350 if (ret != LDB_SUCCESS) {
351 talloc_free(tmp_ctx);
352 return ret;
355 ret = dsdb_request_add_controls(req, dsdb_flags);
356 if (ret != LDB_SUCCESS) {
357 talloc_free(tmp_ctx);
358 return ret;
361 /* Run the new request */
362 if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
363 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
364 ret = ops->add(module, req);
365 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
366 ret = ldb_request(ldb_module_get_ctx(module), req);
367 } else {
368 ret = ldb_next_request(module, req);
370 if (ret == LDB_SUCCESS) {
371 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
374 talloc_free(tmp_ctx);
375 return ret;
379 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
381 const struct dsdb_class *last_class = NULL;
382 unsigned int i;
384 for (i = 0; i < element->num_values; i++){
385 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
387 if(tmp_class == NULL) {
388 continue;
391 if(tmp_class->objectClassCategory == 3) {
392 continue;
395 if (!last_class) {
396 last_class = tmp_class;
397 } else {
398 if (tmp_class->subClass_order > last_class->subClass_order)
399 last_class = tmp_class;
403 return last_class;
407 check if a single valued link has multiple non-deleted values
409 This is needed when we will be using the RELAX control to stop
410 ldb_tdb from checking single valued links
412 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
413 const struct ldb_message_element *el)
415 bool found_active = false;
416 unsigned int i;
418 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
419 el->num_values < 2) {
420 return LDB_SUCCESS;
423 for (i=0; i<el->num_values; i++) {
424 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
425 if (found_active) {
426 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
428 found_active = true;
432 return LDB_SUCCESS;
435 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
436 struct GUID op_feature_guid, bool *feature_enabled)
438 TALLOC_CTX *tmp_ctx;
439 struct ldb_context *ldb = ldb_module_get_ctx(module);
440 struct ldb_result *res;
441 struct ldb_dn *search_dn;
442 struct GUID search_guid;
443 const char *attrs[] = {"msDS-EnabledFeature", NULL};
444 int ret;
445 unsigned int i;
446 struct ldb_message_element *el;
448 *feature_enabled = false;
450 tmp_ctx = talloc_new(ldb);
452 ret = ldb_search(ldb, tmp_ctx, &res,
453 scope, LDB_SCOPE_BASE, attrs,
454 NULL);
455 if (ret != LDB_SUCCESS) {
456 ldb_asprintf_errstring(ldb,
457 "Could no find the scope object - dn: %s\n",
458 ldb_dn_get_linearized(scope));
459 talloc_free(tmp_ctx);
460 return LDB_ERR_OPERATIONS_ERROR;
462 if (res->msgs[0]->num_elements > 0) {
464 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
466 attrs[0] = "msDS-OptionalFeatureGUID";
468 for (i=0; i<el->num_values; i++) {
469 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
471 ret = ldb_search(ldb, tmp_ctx, &res,
472 search_dn, LDB_SCOPE_BASE, attrs,
473 NULL);
474 if (ret != LDB_SUCCESS) {
475 ldb_asprintf_errstring(ldb,
476 "Could no find object dn: %s\n",
477 ldb_dn_get_linearized(search_dn));
478 talloc_free(tmp_ctx);
479 return LDB_ERR_OPERATIONS_ERROR;
482 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
484 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
485 *feature_enabled = true;
486 break;
490 talloc_free(tmp_ctx);
491 return LDB_SUCCESS;
495 find a 'reference' DN that points at another object
496 (eg. serverReference, rIDManagerReference etc)
498 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
499 const char *attribute, struct ldb_dn **dn)
501 const char *attrs[2];
502 struct ldb_result *res;
503 int ret;
505 attrs[0] = attribute;
506 attrs[1] = NULL;
508 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs, 0);
509 if (ret != LDB_SUCCESS) {
510 return ret;
513 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
514 mem_ctx, res->msgs[0], attribute);
515 if (!*dn) {
516 talloc_free(res);
517 return LDB_ERR_NO_SUCH_ATTRIBUTE;
520 talloc_free(res);
521 return LDB_SUCCESS;
525 find the RID Manager$ DN via the rIDManagerReference attribute in the
526 base DN
528 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
530 return dsdb_module_reference_dn(module, mem_ctx,
531 ldb_get_default_basedn(ldb_module_get_ctx(module)),
532 "rIDManagerReference", dn);
537 update an integer attribute safely via a constrained delete/add
539 int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
540 const char *attr, uint64_t old_val, uint64_t new_val)
542 struct ldb_message *msg;
543 struct ldb_message_element *el;
544 struct ldb_val v1, v2;
545 int ret;
546 char *vstring;
548 msg = ldb_msg_new(module);
549 msg->dn = dn;
551 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
552 if (ret != LDB_SUCCESS) {
553 talloc_free(msg);
554 return ret;
556 el->num_values = 1;
557 el->values = &v1;
558 vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
559 if (!vstring) {
560 ldb_module_oom(module);
561 talloc_free(msg);
562 return LDB_ERR_OPERATIONS_ERROR;
564 v1 = data_blob_string_const(vstring);
566 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
567 if (ret != LDB_SUCCESS) {
568 talloc_free(msg);
569 return ret;
571 el->num_values = 1;
572 el->values = &v2;
573 vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
574 if (!vstring) {
575 ldb_module_oom(module);
576 talloc_free(msg);
577 return LDB_ERR_OPERATIONS_ERROR;
579 v2 = data_blob_string_const(vstring);
581 ret = dsdb_module_modify(module, msg, 0);
582 talloc_free(msg);
583 return ret;
587 used to chain to the callers callback
589 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
591 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
593 talloc_steal(up_req, req);
594 return up_req->callback(up_req, ares);
599 set an integer attribute
601 int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
602 const char *attr, uint64_t new_val)
604 struct ldb_message *msg;
605 int ret;
607 msg = ldb_msg_new(module);
608 msg->dn = dn;
610 ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
611 if (ret != LDB_SUCCESS) {
612 talloc_free(msg);
613 return ret;
615 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
617 ret = dsdb_module_modify(module, msg, 0);
618 talloc_free(msg);
619 return ret;
623 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
624 object for a partition
626 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
627 uint64_t *uSN, uint64_t *urgent_uSN)
629 struct ldb_context *ldb = ldb_module_get_ctx(module);
630 struct ldb_request *req;
631 int ret;
632 TALLOC_CTX *tmp_ctx = talloc_new(module);
633 struct dsdb_control_current_partition *p_ctrl;
634 struct ldb_result *res;
636 res = talloc_zero(tmp_ctx, struct ldb_result);
637 if (!res) {
638 talloc_free(tmp_ctx);
639 return LDB_ERR_OPERATIONS_ERROR;
642 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
643 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
644 LDB_SCOPE_BASE,
645 NULL, NULL,
646 NULL,
647 res, ldb_search_default_callback,
648 NULL);
649 if (ret != LDB_SUCCESS) {
650 talloc_free(tmp_ctx);
651 return ret;
654 p_ctrl = talloc(req, struct dsdb_control_current_partition);
655 if (p_ctrl == NULL) {
656 talloc_free(res);
657 return LDB_ERR_OPERATIONS_ERROR;
659 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
660 p_ctrl->dn = dn;
663 ret = ldb_request_add_control(req,
664 DSDB_CONTROL_CURRENT_PARTITION_OID,
665 false, p_ctrl);
666 if (ret != LDB_SUCCESS) {
667 talloc_free(tmp_ctx);
668 return ret;
671 /* Run the new request */
672 ret = ldb_next_request(module, req);
674 if (ret == LDB_SUCCESS) {
675 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
678 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
679 /* it hasn't been created yet, which means
680 an implicit value of zero */
681 *uSN = 0;
682 talloc_free(tmp_ctx);
683 return LDB_SUCCESS;
686 if (ret != LDB_SUCCESS) {
687 talloc_free(tmp_ctx);
688 return ret;
691 if (res->count < 1) {
692 *uSN = 0;
693 if (urgent_uSN) {
694 *urgent_uSN = 0;
696 } else {
697 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
698 if (urgent_uSN) {
699 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
703 talloc_free(tmp_ctx);
705 return LDB_SUCCESS;
709 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
710 partition
712 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
713 uint64_t uSN, uint64_t urgent_uSN)
715 struct ldb_context *ldb = ldb_module_get_ctx(module);
716 struct ldb_request *req;
717 struct ldb_message *msg;
718 struct dsdb_control_current_partition *p_ctrl;
719 int ret;
721 msg = ldb_msg_new(module);
722 if (msg == NULL) {
723 return LDB_ERR_OPERATIONS_ERROR;
726 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
727 if (msg->dn == NULL) {
728 talloc_free(msg);
729 return LDB_ERR_OPERATIONS_ERROR;
732 ret = ldb_msg_add_fmt(msg, "uSNHighest", "%llu", (unsigned long long)uSN);
733 if (ret != LDB_SUCCESS) {
734 talloc_free(msg);
735 return ret;
737 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
739 /* urgent_uSN is optional so may not be stored */
740 if (urgent_uSN) {
741 ret = ldb_msg_add_fmt(msg, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN);
742 if (ret != LDB_SUCCESS) {
743 talloc_free(msg);
744 return ret;
746 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
750 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
751 if (p_ctrl == NULL) {
752 talloc_free(msg);
753 return LDB_ERR_OPERATIONS_ERROR;
755 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
756 p_ctrl->dn = dn;
758 ret = ldb_build_mod_req(&req, ldb, msg,
759 msg,
760 NULL,
761 NULL, ldb_op_default_callback,
762 NULL);
763 again:
764 if (ret != LDB_SUCCESS) {
765 talloc_free(msg);
766 return ret;
769 ret = ldb_request_add_control(req,
770 DSDB_CONTROL_CURRENT_PARTITION_OID,
771 false, p_ctrl);
772 if (ret != LDB_SUCCESS) {
773 talloc_free(msg);
774 return ret;
777 /* Run the new request */
778 ret = ldb_next_request(module, req);
780 if (ret == LDB_SUCCESS) {
781 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
783 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
784 ret = ldb_build_add_req(&req, ldb, msg,
785 msg,
786 NULL,
787 NULL, ldb_op_default_callback,
788 NULL);
789 goto again;
792 talloc_free(msg);
794 return ret;
797 bool dsdb_module_am_system(struct ldb_module *module)
799 struct ldb_context *ldb = ldb_module_get_ctx(module);
800 struct auth_session_info *session_info
801 = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
802 return security_session_user_level(session_info) == SECURITY_SYSTEM;
806 check if the recyclebin is enabled
808 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
810 struct ldb_context *ldb = ldb_module_get_ctx(module);
811 struct ldb_dn *partitions_dn;
812 struct GUID recyclebin_guid;
813 int ret;
815 partitions_dn = samdb_partitions_dn(ldb, module);
817 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
819 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
820 if (ret != LDB_SUCCESS) {
821 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
822 talloc_free(partitions_dn);
823 return LDB_ERR_UNWILLING_TO_PERFORM;
826 talloc_free(partitions_dn);
827 return LDB_SUCCESS;