2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 2009
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "ldb_module.h"
25 #include "librpc/ndr/libndr.h"
26 #include "dsdb/samdb/ldb_modules/util.h"
27 #include "dsdb/samdb/samdb.h"
29 #include "libcli/security/security.h"
32 search for attrs on one DN, in the modules below
34 int dsdb_module_search_dn(struct ldb_module *module,
36 struct ldb_result **_res,
37 struct ldb_dn *basedn,
38 const char * const *attrs,
42 struct ldb_request *req;
44 struct ldb_result *res;
46 tmp_ctx = talloc_new(mem_ctx);
48 res = talloc_zero(tmp_ctx, struct ldb_result);
51 return ldb_oom(ldb_module_get_ctx(module));
54 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
61 ldb_search_default_callback,
63 if (ret != LDB_SUCCESS) {
68 ret = dsdb_request_add_controls(req, dsdb_flags);
69 if (ret != LDB_SUCCESS) {
74 /* Run the new request */
75 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
76 ret = ldb_next_request(module, req);
77 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
78 ret = ldb_request(ldb_module_get_ctx(module), req);
80 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
81 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
82 ret = ops->modify(module, req);
84 if (ret == LDB_SUCCESS) {
85 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
88 if (ret != LDB_SUCCESS) {
93 if (res->count != 1) {
94 /* we may be reading a DB that does not have the 'check base on search' option... */
95 ret = LDB_ERR_NO_SUCH_OBJECT;
96 ldb_asprintf_errstring(ldb_module_get_ctx(module),
97 "dsdb_module_search_dn: did not find base dn %s (%d results)",
98 ldb_dn_get_linearized(basedn), res->count);
100 *_res = talloc_steal(mem_ctx, res);
102 talloc_free(tmp_ctx);
107 search for attrs in the modules below
109 int dsdb_module_search(struct ldb_module *module,
111 struct ldb_result **_res,
112 struct ldb_dn *basedn, enum ldb_scope scope,
113 const char * const *attrs,
115 const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
118 struct ldb_request *req;
120 struct ldb_result *res;
124 tmp_ctx = talloc_new(mem_ctx);
127 va_start(ap, format);
128 expression = talloc_vasprintf(tmp_ctx, format, ap);
132 talloc_free(tmp_ctx);
133 return ldb_oom(ldb_module_get_ctx(module));
139 res = talloc_zero(tmp_ctx, struct ldb_result);
141 talloc_free(tmp_ctx);
142 return ldb_oom(ldb_module_get_ctx(module));
145 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
152 ldb_search_default_callback,
154 if (ret != LDB_SUCCESS) {
155 talloc_free(tmp_ctx);
159 ret = dsdb_request_add_controls(req, dsdb_flags);
160 if (ret != LDB_SUCCESS) {
161 talloc_free(tmp_ctx);
165 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
166 ret = ldb_next_request(module, req);
167 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
168 ret = ldb_request(ldb_module_get_ctx(module), req);
170 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
171 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
172 ret = ops->search(module, req);
174 if (ret == LDB_SUCCESS) {
175 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
179 if (ret == LDB_SUCCESS) {
180 *_res = talloc_steal(mem_ctx, res);
182 talloc_free(tmp_ctx);
187 find a DN given a GUID. This searches across all partitions
189 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
190 const struct GUID *guid, struct ldb_dn **dn)
192 struct ldb_result *res;
193 const char *attrs[] = { NULL };
194 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
197 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
199 DSDB_FLAG_NEXT_MODULE |
200 DSDB_SEARCH_SHOW_DELETED |
201 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
202 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
203 "objectGUID=%s", GUID_string(tmp_ctx, guid));
204 if (ret != LDB_SUCCESS) {
205 talloc_free(tmp_ctx);
208 if (res->count == 0) {
209 talloc_free(tmp_ctx);
210 return LDB_ERR_NO_SUCH_OBJECT;
212 if (res->count != 1) {
213 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
214 GUID_string(tmp_ctx, guid));
215 talloc_free(tmp_ctx);
216 return LDB_ERR_OPERATIONS_ERROR;
219 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
221 talloc_free(tmp_ctx);
226 find a GUID given a DN.
228 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
230 const char *attrs[] = { NULL };
231 struct ldb_result *res;
232 TALLOC_CTX *tmp_ctx = talloc_new(module);
236 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
237 DSDB_FLAG_NEXT_MODULE |
238 DSDB_SEARCH_SHOW_DELETED |
239 DSDB_SEARCH_SHOW_EXTENDED_DN);
240 if (ret != LDB_SUCCESS) {
241 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
242 ldb_dn_get_linearized(dn));
243 talloc_free(tmp_ctx);
247 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
248 if (!NT_STATUS_IS_OK(status)) {
249 talloc_free(tmp_ctx);
250 return ldb_operr(ldb_module_get_ctx(module));
253 talloc_free(tmp_ctx);
258 a ldb_modify request operating on modules below the
261 int dsdb_module_modify(struct ldb_module *module,
262 const struct ldb_message *message,
265 struct ldb_request *mod_req;
267 struct ldb_context *ldb = ldb_module_get_ctx(module);
268 TALLOC_CTX *tmp_ctx = talloc_new(module);
269 struct ldb_result *res;
271 res = talloc_zero(tmp_ctx, struct ldb_result);
273 talloc_free(tmp_ctx);
274 return ldb_oom(ldb_module_get_ctx(module));
277 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
281 ldb_modify_default_callback,
283 if (ret != LDB_SUCCESS) {
284 talloc_free(tmp_ctx);
288 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
289 if (ret != LDB_SUCCESS) {
290 talloc_free(tmp_ctx);
294 /* Run the new request */
295 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
296 ret = ldb_next_request(module, mod_req);
297 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
298 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
300 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
301 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
302 ret = ops->modify(module, mod_req);
304 if (ret == LDB_SUCCESS) {
305 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
308 talloc_free(tmp_ctx);
315 a ldb_rename request operating on modules below the
318 int dsdb_module_rename(struct ldb_module *module,
319 struct ldb_dn *olddn, struct ldb_dn *newdn,
322 struct ldb_request *req;
324 struct ldb_context *ldb = ldb_module_get_ctx(module);
325 TALLOC_CTX *tmp_ctx = talloc_new(module);
326 struct ldb_result *res;
328 res = talloc_zero(tmp_ctx, struct ldb_result);
330 talloc_free(tmp_ctx);
331 return ldb_oom(ldb_module_get_ctx(module));
334 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
339 ldb_modify_default_callback,
341 if (ret != LDB_SUCCESS) {
342 talloc_free(tmp_ctx);
346 ret = dsdb_request_add_controls(req, dsdb_flags);
347 if (ret != LDB_SUCCESS) {
348 talloc_free(tmp_ctx);
352 /* Run the new request */
353 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
354 ret = ldb_next_request(module, req);
355 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
356 ret = ldb_request(ldb_module_get_ctx(module), req);
358 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
359 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
360 ret = ops->rename(module, req);
362 if (ret == LDB_SUCCESS) {
363 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
366 talloc_free(tmp_ctx);
371 a ldb_add request operating on modules below the
374 int dsdb_module_add(struct ldb_module *module,
375 const struct ldb_message *message,
378 struct ldb_request *req;
380 struct ldb_context *ldb = ldb_module_get_ctx(module);
381 TALLOC_CTX *tmp_ctx = talloc_new(module);
382 struct ldb_result *res;
384 res = talloc_zero(tmp_ctx, struct ldb_result);
386 talloc_free(tmp_ctx);
387 return ldb_oom(ldb_module_get_ctx(module));
390 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
394 ldb_modify_default_callback,
396 if (ret != LDB_SUCCESS) {
397 talloc_free(tmp_ctx);
401 ret = dsdb_request_add_controls(req, dsdb_flags);
402 if (ret != LDB_SUCCESS) {
403 talloc_free(tmp_ctx);
407 /* Run the new request */
408 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
409 ret = ldb_next_request(module, req);
410 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
411 ret = ldb_request(ldb_module_get_ctx(module), req);
413 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
414 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
415 ret = ops->add(module, req);
417 if (ret == LDB_SUCCESS) {
418 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
421 talloc_free(tmp_ctx);
426 a ldb_delete request operating on modules below the
429 int dsdb_module_del(struct ldb_module *module,
433 struct ldb_request *req;
435 struct ldb_context *ldb = ldb_module_get_ctx(module);
436 TALLOC_CTX *tmp_ctx = talloc_new(module);
437 struct ldb_result *res;
439 res = talloc_zero(tmp_ctx, struct ldb_result);
441 talloc_free(tmp_ctx);
445 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
449 ldb_modify_default_callback,
451 if (ret != LDB_SUCCESS) {
452 talloc_free(tmp_ctx);
456 ret = dsdb_request_add_controls(req, dsdb_flags);
457 if (ret != LDB_SUCCESS) {
458 talloc_free(tmp_ctx);
462 /* Run the new request */
463 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
464 ret = ldb_next_request(module, req);
465 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
466 ret = ldb_request(ldb_module_get_ctx(module), req);
468 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
469 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
470 ret = ops->del(module, req);
472 if (ret == LDB_SUCCESS) {
473 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
476 talloc_free(tmp_ctx);
480 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
482 const struct dsdb_class *last_class = NULL;
485 for (i = 0; i < element->num_values; i++){
486 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
488 if(tmp_class == NULL) {
492 if(tmp_class->objectClassCategory > 1) {
497 last_class = tmp_class;
499 if (tmp_class->subClass_order > last_class->subClass_order)
500 last_class = tmp_class;
508 check if a single valued link has multiple non-deleted values
510 This is needed when we will be using the RELAX control to stop
511 ldb_tdb from checking single valued links
513 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
514 const struct ldb_message_element *el)
516 bool found_active = false;
519 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
520 el->num_values < 2) {
524 for (i=0; i<el->num_values; i++) {
525 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
527 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
536 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
537 struct GUID op_feature_guid, bool *feature_enabled)
540 struct ldb_context *ldb = ldb_module_get_ctx(module);
541 struct ldb_result *res;
542 struct ldb_dn *search_dn;
543 struct GUID search_guid;
544 const char *attrs[] = {"msDS-EnabledFeature", NULL};
547 struct ldb_message_element *el;
549 *feature_enabled = false;
551 tmp_ctx = talloc_new(ldb);
553 ret = ldb_search(ldb, tmp_ctx, &res,
554 scope, LDB_SCOPE_BASE, attrs,
556 if (ret != LDB_SUCCESS) {
557 ldb_asprintf_errstring(ldb,
558 "Could no find the scope object - dn: %s\n",
559 ldb_dn_get_linearized(scope));
560 talloc_free(tmp_ctx);
561 return LDB_ERR_OPERATIONS_ERROR;
563 if (res->msgs[0]->num_elements > 0) {
565 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
567 attrs[0] = "msDS-OptionalFeatureGUID";
569 for (i=0; i<el->num_values; i++) {
570 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
572 ret = ldb_search(ldb, tmp_ctx, &res,
573 search_dn, LDB_SCOPE_BASE, attrs,
575 if (ret != LDB_SUCCESS) {
576 ldb_asprintf_errstring(ldb,
577 "Could no find object dn: %s\n",
578 ldb_dn_get_linearized(search_dn));
579 talloc_free(tmp_ctx);
580 return LDB_ERR_OPERATIONS_ERROR;
583 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
585 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
586 *feature_enabled = true;
591 talloc_free(tmp_ctx);
596 find a 'reference' DN that points at another object
597 (eg. serverReference, rIDManagerReference etc)
599 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
600 const char *attribute, struct ldb_dn **dn)
602 const char *attrs[2];
603 struct ldb_result *res;
606 attrs[0] = attribute;
609 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
610 DSDB_FLAG_NEXT_MODULE);
611 if (ret != LDB_SUCCESS) {
615 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
616 mem_ctx, res->msgs[0], attribute);
619 return LDB_ERR_NO_SUCH_ATTRIBUTE;
627 find the RID Manager$ DN via the rIDManagerReference attribute in the
630 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
632 return dsdb_module_reference_dn(module, mem_ctx,
633 ldb_get_default_basedn(ldb_module_get_ctx(module)),
634 "rIDManagerReference", dn);
639 update an integer attribute safely via a constrained delete/add
641 int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
642 const char *attr, uint64_t old_val, uint64_t new_val)
644 struct ldb_message *msg;
645 struct ldb_message_element *el;
646 struct ldb_val v1, v2;
650 msg = ldb_msg_new(module);
653 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
654 if (ret != LDB_SUCCESS) {
660 vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
663 return ldb_module_oom(module);
665 v1 = data_blob_string_const(vstring);
667 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
668 if (ret != LDB_SUCCESS) {
674 vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
677 return ldb_module_oom(module);
679 v2 = data_blob_string_const(vstring);
681 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
687 used to chain to the callers callback
689 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
691 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
693 talloc_steal(up_req, req);
694 return up_req->callback(up_req, ares);
699 set an integer attribute
701 int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
702 const char *attr, uint64_t new_val)
704 struct ldb_message *msg;
707 msg = ldb_msg_new(module);
710 ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
711 if (ret != LDB_SUCCESS) {
715 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
717 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
723 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
724 object for a partition
726 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
727 uint64_t *uSN, uint64_t *urgent_uSN)
729 struct ldb_context *ldb = ldb_module_get_ctx(module);
730 struct ldb_request *req;
732 TALLOC_CTX *tmp_ctx = talloc_new(module);
733 struct dsdb_control_current_partition *p_ctrl;
734 struct ldb_result *res;
736 res = talloc_zero(tmp_ctx, struct ldb_result);
738 talloc_free(tmp_ctx);
739 return ldb_module_oom(module);
742 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
743 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
747 res, ldb_search_default_callback,
749 if (ret != LDB_SUCCESS) {
750 talloc_free(tmp_ctx);
754 p_ctrl = talloc(req, struct dsdb_control_current_partition);
755 if (p_ctrl == NULL) {
756 talloc_free(tmp_ctx);
757 return ldb_module_oom(module);
759 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
763 ret = ldb_request_add_control(req,
764 DSDB_CONTROL_CURRENT_PARTITION_OID,
766 if (ret != LDB_SUCCESS) {
767 talloc_free(tmp_ctx);
771 /* Run the new request */
772 ret = ldb_next_request(module, req);
774 if (ret == LDB_SUCCESS) {
775 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
778 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
779 /* it hasn't been created yet, which means
780 an implicit value of zero */
782 talloc_free(tmp_ctx);
786 if (ret != LDB_SUCCESS) {
787 talloc_free(tmp_ctx);
791 if (res->count != 1) {
797 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
799 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
803 talloc_free(tmp_ctx);
809 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
812 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
813 uint64_t uSN, uint64_t urgent_uSN)
815 struct ldb_context *ldb = ldb_module_get_ctx(module);
816 struct ldb_request *req;
817 struct ldb_message *msg;
818 struct dsdb_control_current_partition *p_ctrl;
820 struct ldb_result *res;
822 msg = ldb_msg_new(module);
824 return ldb_module_oom(module);
827 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
828 if (msg->dn == NULL) {
830 return ldb_operr(ldb_module_get_ctx(module));
833 res = talloc_zero(msg, struct ldb_result);
836 return ldb_module_oom(module);
839 ret = ldb_msg_add_fmt(msg, "uSNHighest", "%llu", (unsigned long long)uSN);
840 if (ret != LDB_SUCCESS) {
844 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
846 /* urgent_uSN is optional so may not be stored */
848 ret = ldb_msg_add_fmt(msg, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN);
849 if (ret != LDB_SUCCESS) {
853 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
857 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
858 if (p_ctrl == NULL) {
862 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
864 ret = ldb_build_mod_req(&req, ldb, msg,
868 ldb_modify_default_callback,
871 if (ret != LDB_SUCCESS) {
876 ret = ldb_request_add_control(req,
877 DSDB_CONTROL_CURRENT_PARTITION_OID,
879 if (ret != LDB_SUCCESS) {
884 /* Run the new request */
885 ret = ldb_next_request(module, req);
887 if (ret == LDB_SUCCESS) {
888 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
890 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
891 ret = ldb_build_add_req(&req, ldb, msg,
895 ldb_modify_default_callback,
905 bool dsdb_module_am_system(struct ldb_module *module)
907 struct ldb_context *ldb = ldb_module_get_ctx(module);
908 struct auth_session_info *session_info
909 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
910 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
913 bool dsdb_module_am_administrator(struct ldb_module *module)
915 struct ldb_context *ldb = ldb_module_get_ctx(module);
916 struct auth_session_info *session_info
917 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
918 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
922 check if the recyclebin is enabled
924 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
926 struct ldb_context *ldb = ldb_module_get_ctx(module);
927 struct ldb_dn *partitions_dn;
928 struct GUID recyclebin_guid;
931 partitions_dn = samdb_partitions_dn(ldb, module);
933 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
935 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
936 if (ret != LDB_SUCCESS) {
937 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
938 talloc_free(partitions_dn);
939 return LDB_ERR_UNWILLING_TO_PERFORM;
942 talloc_free(partitions_dn);
946 bool is_attr_in_list(const char * const * attrs, const char *attr)
950 for (i = 0; attrs[i]; i++) {
951 if (ldb_attr_cmp(attrs[i], attr) == 0)
958 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
959 struct ldb_message *msg,
961 const int32_t *old_val,
962 const int32_t *new_val)
964 struct ldb_message_element *el;
969 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
970 if (ret != LDB_SUCCESS) {
974 el->values = talloc_array(msg, struct ldb_val, el->num_values);
976 return ldb_module_oom(module);
978 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
980 return ldb_module_oom(module);
982 *el->values = data_blob_string_const(vstring);
986 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
987 if (ret != LDB_SUCCESS) {
991 el->values = talloc_array(msg, struct ldb_val, el->num_values);
993 return ldb_module_oom(module);
995 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
997 return ldb_module_oom(module);
999 *el->values = data_blob_string_const(vstring);
1005 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1006 struct ldb_message *msg,
1008 const uint32_t *old_val,
1009 const uint32_t *new_val)
1011 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1012 (const int32_t *)old_val,
1013 (const int32_t *)new_val);
1016 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1017 struct ldb_message *msg,
1019 const int64_t *old_val,
1020 const int64_t *new_val)
1022 struct ldb_message_element *el;
1027 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1028 if (ret != LDB_SUCCESS) {
1032 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1034 return ldb_module_oom(module);
1036 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1038 return ldb_module_oom(module);
1040 *el->values = data_blob_string_const(vstring);
1044 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1045 if (ret != LDB_SUCCESS) {
1049 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1051 return ldb_module_oom(module);
1053 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1055 return ldb_module_oom(module);
1057 *el->values = data_blob_string_const(vstring);
1063 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1064 struct ldb_message *msg,
1066 const uint64_t *old_val,
1067 const uint64_t *new_val)
1069 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1070 (const int64_t *)old_val,
1071 (const int64_t *)new_val);
1075 update an int32 attribute safely via a constrained delete/add
1077 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1080 const int32_t *old_val,
1081 const int32_t *new_val)
1083 struct ldb_message *msg;
1086 msg = ldb_msg_new(module);
1089 ret = dsdb_msg_constrainted_update_int32(module,
1093 if (ret != LDB_SUCCESS) {
1098 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1103 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1106 const uint32_t *old_val,
1107 const uint32_t *new_val)
1109 return dsdb_module_constrainted_update_int32(module, dn, attr,
1110 (const int32_t *)old_val,
1111 (const int32_t *)new_val);
1115 update an int64 attribute safely via a constrained delete/add
1117 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1120 const int64_t *old_val,
1121 const int64_t *new_val)
1123 struct ldb_message *msg;
1126 msg = ldb_msg_new(module);
1129 ret = dsdb_msg_constrainted_update_int64(module,
1133 if (ret != LDB_SUCCESS) {
1138 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1143 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1146 const uint64_t *old_val,
1147 const uint64_t *new_val)
1149 return dsdb_module_constrainted_update_int64(module, dn, attr,
1150 (const int64_t *)old_val,
1151 (const int64_t *)new_val);
1155 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1156 TALLOC_CTX *mem_ctx)
1159 struct ldb_dn *new_dn;
1160 struct ldb_context *ldb = ldb_module_get_ctx(module);
1161 static const char *attrs[] = { "dsHeuristics", NULL };
1162 struct ldb_result *res;
1164 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1165 if (!ldb_dn_add_child_fmt(new_dn,
1166 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1167 talloc_free(new_dn);
1170 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1173 DSDB_FLAG_NEXT_MODULE);
1174 if (ret == LDB_SUCCESS && res->count == 1) {
1175 return ldb_msg_find_ldb_val(res->msgs[0],
1181 bool dsdb_block_anonymous_ops(struct ldb_module *module,
1182 TALLOC_CTX *mem_ctx)
1184 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1185 struct ldb_context *ldb = ldb_module_get_ctx(module);
1187 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1189 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1191 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1197 talloc_free(tmp_ctx);