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,
40 struct ldb_request *parent)
43 struct ldb_request *req;
45 struct ldb_result *res;
47 tmp_ctx = talloc_new(mem_ctx);
49 res = talloc_zero(tmp_ctx, struct ldb_result);
52 return ldb_oom(ldb_module_get_ctx(module));
55 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
62 ldb_search_default_callback,
64 LDB_REQ_SET_LOCATION(req);
65 if (ret != LDB_SUCCESS) {
70 ret = dsdb_request_add_controls(req, dsdb_flags);
71 if (ret != LDB_SUCCESS) {
76 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
77 ldb_req_mark_trusted(req);
80 /* Run the new request */
81 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
82 ret = ldb_next_request(module, req);
83 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
84 ret = ldb_request(ldb_module_get_ctx(module), req);
86 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
87 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
88 ret = ops->search(module, req);
90 if (ret == LDB_SUCCESS) {
91 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
94 if (ret != LDB_SUCCESS) {
99 if (res->count != 1) {
100 /* we may be reading a DB that does not have the 'check base on search' option... */
101 ret = LDB_ERR_NO_SUCH_OBJECT;
102 ldb_asprintf_errstring(ldb_module_get_ctx(module),
103 "dsdb_module_search_dn: did not find base dn %s (%d results)",
104 ldb_dn_get_linearized(basedn), res->count);
106 *_res = talloc_steal(mem_ctx, res);
108 talloc_free(tmp_ctx);
113 search for attrs in the modules below
115 int dsdb_module_search(struct ldb_module *module,
117 struct ldb_result **_res,
118 struct ldb_dn *basedn, enum ldb_scope scope,
119 const char * const *attrs,
121 struct ldb_request *parent,
122 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
125 struct ldb_request *req;
127 struct ldb_result *res;
131 tmp_ctx = talloc_new(mem_ctx);
134 va_start(ap, format);
135 expression = talloc_vasprintf(tmp_ctx, format, ap);
139 talloc_free(tmp_ctx);
140 return ldb_oom(ldb_module_get_ctx(module));
146 res = talloc_zero(tmp_ctx, struct ldb_result);
148 talloc_free(tmp_ctx);
149 return ldb_oom(ldb_module_get_ctx(module));
152 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
159 ldb_search_default_callback,
161 LDB_REQ_SET_LOCATION(req);
162 if (ret != LDB_SUCCESS) {
163 talloc_free(tmp_ctx);
167 ret = dsdb_request_add_controls(req, dsdb_flags);
168 if (ret != LDB_SUCCESS) {
169 talloc_free(tmp_ctx);
173 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
174 ldb_req_mark_trusted(req);
177 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
178 ret = ldb_next_request(module, req);
179 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
180 ret = ldb_request(ldb_module_get_ctx(module), req);
182 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
183 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
184 ret = ops->search(module, req);
186 if (ret == LDB_SUCCESS) {
187 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
191 if (ret == LDB_SUCCESS) {
192 *_res = talloc_steal(mem_ctx, res);
194 talloc_free(tmp_ctx);
199 find a DN given a GUID. This searches across all partitions
201 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
202 const struct GUID *guid, struct ldb_dn **dn,
203 struct ldb_request *parent)
205 struct ldb_result *res;
206 const char *attrs[] = { NULL };
207 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
210 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
212 DSDB_FLAG_NEXT_MODULE |
213 DSDB_SEARCH_SHOW_RECYCLED |
214 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
215 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
217 "objectGUID=%s", GUID_string(tmp_ctx, guid));
218 if (ret != LDB_SUCCESS) {
219 talloc_free(tmp_ctx);
222 if (res->count == 0) {
223 talloc_free(tmp_ctx);
224 return LDB_ERR_NO_SUCH_OBJECT;
226 if (res->count != 1) {
227 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
228 GUID_string(tmp_ctx, guid));
229 talloc_free(tmp_ctx);
230 return LDB_ERR_OPERATIONS_ERROR;
233 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
235 talloc_free(tmp_ctx);
240 find a GUID given a DN.
242 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
243 struct ldb_request *parent)
245 const char *attrs[] = { NULL };
246 struct ldb_result *res;
247 TALLOC_CTX *tmp_ctx = talloc_new(module);
251 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
252 DSDB_FLAG_NEXT_MODULE |
253 DSDB_SEARCH_SHOW_RECYCLED |
254 DSDB_SEARCH_SHOW_EXTENDED_DN,
256 if (ret != LDB_SUCCESS) {
257 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
258 ldb_dn_get_linearized(dn));
259 talloc_free(tmp_ctx);
263 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
264 if (!NT_STATUS_IS_OK(status)) {
265 talloc_free(tmp_ctx);
266 return ldb_operr(ldb_module_get_ctx(module));
269 talloc_free(tmp_ctx);
274 a ldb_modify request operating on modules below the
277 int dsdb_module_modify(struct ldb_module *module,
278 const struct ldb_message *message,
280 struct ldb_request *parent)
282 struct ldb_request *mod_req;
284 struct ldb_context *ldb = ldb_module_get_ctx(module);
285 TALLOC_CTX *tmp_ctx = talloc_new(module);
286 struct ldb_result *res;
288 res = talloc_zero(tmp_ctx, struct ldb_result);
290 talloc_free(tmp_ctx);
291 return ldb_oom(ldb_module_get_ctx(module));
294 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
298 ldb_modify_default_callback,
300 LDB_REQ_SET_LOCATION(mod_req);
301 if (ret != LDB_SUCCESS) {
302 talloc_free(tmp_ctx);
306 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
307 if (ret != LDB_SUCCESS) {
308 talloc_free(tmp_ctx);
312 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
313 ldb_req_mark_trusted(mod_req);
316 /* Run the new request */
317 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
318 ret = ldb_next_request(module, mod_req);
319 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
320 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
322 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
323 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
324 ret = ops->modify(module, mod_req);
326 if (ret == LDB_SUCCESS) {
327 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
330 talloc_free(tmp_ctx);
337 a ldb_rename request operating on modules below the
340 int dsdb_module_rename(struct ldb_module *module,
341 struct ldb_dn *olddn, struct ldb_dn *newdn,
343 struct ldb_request *parent)
345 struct ldb_request *req;
347 struct ldb_context *ldb = ldb_module_get_ctx(module);
348 TALLOC_CTX *tmp_ctx = talloc_new(module);
349 struct ldb_result *res;
351 res = talloc_zero(tmp_ctx, struct ldb_result);
353 talloc_free(tmp_ctx);
354 return ldb_oom(ldb_module_get_ctx(module));
357 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
362 ldb_modify_default_callback,
364 LDB_REQ_SET_LOCATION(req);
365 if (ret != LDB_SUCCESS) {
366 talloc_free(tmp_ctx);
370 ret = dsdb_request_add_controls(req, dsdb_flags);
371 if (ret != LDB_SUCCESS) {
372 talloc_free(tmp_ctx);
376 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
377 ldb_req_mark_trusted(req);
380 /* Run the new request */
381 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
382 ret = ldb_next_request(module, req);
383 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
384 ret = ldb_request(ldb_module_get_ctx(module), req);
386 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
387 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
388 ret = ops->rename(module, req);
390 if (ret == LDB_SUCCESS) {
391 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
394 talloc_free(tmp_ctx);
399 a ldb_add request operating on modules below the
402 int dsdb_module_add(struct ldb_module *module,
403 const struct ldb_message *message,
405 struct ldb_request *parent)
407 struct ldb_request *req;
409 struct ldb_context *ldb = ldb_module_get_ctx(module);
410 TALLOC_CTX *tmp_ctx = talloc_new(module);
411 struct ldb_result *res;
413 res = talloc_zero(tmp_ctx, struct ldb_result);
415 talloc_free(tmp_ctx);
416 return ldb_oom(ldb_module_get_ctx(module));
419 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
423 ldb_modify_default_callback,
425 LDB_REQ_SET_LOCATION(req);
426 if (ret != LDB_SUCCESS) {
427 talloc_free(tmp_ctx);
431 ret = dsdb_request_add_controls(req, dsdb_flags);
432 if (ret != LDB_SUCCESS) {
433 talloc_free(tmp_ctx);
437 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
438 ldb_req_mark_trusted(req);
441 /* Run the new request */
442 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
443 ret = ldb_next_request(module, req);
444 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
445 ret = ldb_request(ldb_module_get_ctx(module), req);
447 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
448 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
449 ret = ops->add(module, req);
451 if (ret == LDB_SUCCESS) {
452 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
455 talloc_free(tmp_ctx);
460 a ldb_delete request operating on modules below the
463 int dsdb_module_del(struct ldb_module *module,
466 struct ldb_request *parent)
468 struct ldb_request *req;
470 struct ldb_context *ldb = ldb_module_get_ctx(module);
471 TALLOC_CTX *tmp_ctx = talloc_new(module);
472 struct ldb_result *res;
474 res = talloc_zero(tmp_ctx, struct ldb_result);
476 talloc_free(tmp_ctx);
480 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
484 ldb_modify_default_callback,
486 LDB_REQ_SET_LOCATION(req);
487 if (ret != LDB_SUCCESS) {
488 talloc_free(tmp_ctx);
492 ret = dsdb_request_add_controls(req, dsdb_flags);
493 if (ret != LDB_SUCCESS) {
494 talloc_free(tmp_ctx);
498 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
499 ldb_req_mark_trusted(req);
502 /* Run the new request */
503 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
504 ret = ldb_next_request(module, req);
505 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
506 ret = ldb_request(ldb_module_get_ctx(module), req);
508 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
509 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
510 ret = ops->del(module, req);
512 if (ret == LDB_SUCCESS) {
513 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
516 talloc_free(tmp_ctx);
521 check if a single valued link has multiple non-deleted values
523 This is needed when we will be using the RELAX control to stop
524 ldb_tdb from checking single valued links
526 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
527 const struct ldb_message_element *el)
529 bool found_active = false;
532 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
533 el->num_values < 2) {
537 for (i=0; i<el->num_values; i++) {
538 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
540 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
549 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
550 struct GUID op_feature_guid, bool *feature_enabled)
553 struct ldb_context *ldb = ldb_module_get_ctx(module);
554 struct ldb_result *res;
555 struct ldb_dn *search_dn;
556 struct GUID search_guid;
557 const char *attrs[] = {"msDS-EnabledFeature", NULL};
560 struct ldb_message_element *el;
562 *feature_enabled = false;
564 tmp_ctx = talloc_new(ldb);
566 ret = ldb_search(ldb, tmp_ctx, &res,
567 scope, LDB_SCOPE_BASE, attrs,
569 if (ret != LDB_SUCCESS) {
570 ldb_asprintf_errstring(ldb,
571 "Could no find the scope object - dn: %s\n",
572 ldb_dn_get_linearized(scope));
573 talloc_free(tmp_ctx);
574 return LDB_ERR_OPERATIONS_ERROR;
576 if (res->msgs[0]->num_elements > 0) {
578 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
580 attrs[0] = "msDS-OptionalFeatureGUID";
582 for (i=0; i<el->num_values; i++) {
583 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
585 ret = ldb_search(ldb, tmp_ctx, &res,
586 search_dn, LDB_SCOPE_BASE, attrs,
588 if (ret != LDB_SUCCESS) {
589 ldb_asprintf_errstring(ldb,
590 "Could no find object dn: %s\n",
591 ldb_dn_get_linearized(search_dn));
592 talloc_free(tmp_ctx);
593 return LDB_ERR_OPERATIONS_ERROR;
596 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
598 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
599 *feature_enabled = true;
604 talloc_free(tmp_ctx);
609 find the NTDS GUID from a computers DN record
611 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
613 struct ldb_dn *computer_dn,
614 struct GUID *ntds_guid,
615 struct ldb_request *parent)
620 *ntds_guid = GUID_zero();
622 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
623 "serverReferenceBL", &dn, parent);
624 if (ret != LDB_SUCCESS) {
628 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
630 return LDB_ERR_OPERATIONS_ERROR;
633 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
639 find a 'reference' DN that points at another object
640 (eg. serverReference, rIDManagerReference etc)
642 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
643 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
645 const char *attrs[2];
646 struct ldb_result *res;
649 attrs[0] = attribute;
652 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
653 DSDB_FLAG_NEXT_MODULE, parent);
654 if (ret != LDB_SUCCESS) {
658 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
659 mem_ctx, res->msgs[0], attribute);
661 ldb_reset_err_string(ldb_module_get_ctx(module));
663 return LDB_ERR_NO_SUCH_ATTRIBUTE;
671 find the RID Manager$ DN via the rIDManagerReference attribute in the
674 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
675 struct ldb_request *parent)
677 return dsdb_module_reference_dn(module, mem_ctx,
678 ldb_get_default_basedn(ldb_module_get_ctx(module)),
679 "rIDManagerReference", dn, parent);
683 used to chain to the callers callback
685 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
687 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
689 talloc_steal(up_req, req);
690 return up_req->callback(up_req, ares);
694 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
695 object for a partition
697 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
698 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
700 struct ldb_context *ldb = ldb_module_get_ctx(module);
701 struct ldb_request *req;
703 TALLOC_CTX *tmp_ctx = talloc_new(module);
704 struct dsdb_control_current_partition *p_ctrl;
705 struct ldb_result *res;
707 res = talloc_zero(tmp_ctx, struct ldb_result);
709 talloc_free(tmp_ctx);
710 return ldb_module_oom(module);
713 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
714 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
718 res, ldb_search_default_callback,
720 LDB_REQ_SET_LOCATION(req);
721 if (ret != LDB_SUCCESS) {
722 talloc_free(tmp_ctx);
726 p_ctrl = talloc(req, struct dsdb_control_current_partition);
727 if (p_ctrl == NULL) {
728 talloc_free(tmp_ctx);
729 return ldb_module_oom(module);
731 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
735 ret = ldb_request_add_control(req,
736 DSDB_CONTROL_CURRENT_PARTITION_OID,
738 if (ret != LDB_SUCCESS) {
739 talloc_free(tmp_ctx);
743 /* Run the new request */
744 ret = ldb_next_request(module, req);
746 if (ret == LDB_SUCCESS) {
747 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
750 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
751 /* it hasn't been created yet, which means
752 an implicit value of zero */
754 talloc_free(tmp_ctx);
755 ldb_reset_err_string(ldb);
759 if (ret != LDB_SUCCESS) {
760 talloc_free(tmp_ctx);
764 if (res->count != 1) {
770 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
772 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
776 talloc_free(tmp_ctx);
782 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
785 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
786 uint64_t uSN, uint64_t urgent_uSN,
787 struct ldb_request *parent)
789 struct ldb_context *ldb = ldb_module_get_ctx(module);
790 struct ldb_request *req;
791 struct ldb_message *msg;
792 struct dsdb_control_current_partition *p_ctrl;
794 struct ldb_result *res;
796 msg = ldb_msg_new(module);
798 return ldb_module_oom(module);
801 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
802 if (msg->dn == NULL) {
804 return ldb_operr(ldb_module_get_ctx(module));
807 res = talloc_zero(msg, struct ldb_result);
810 return ldb_module_oom(module);
813 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
814 if (ret != LDB_SUCCESS) {
818 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
820 /* urgent_uSN is optional so may not be stored */
822 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
824 if (ret != LDB_SUCCESS) {
828 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
832 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
833 if (p_ctrl == NULL) {
837 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
839 ret = ldb_build_mod_req(&req, ldb, msg,
843 ldb_modify_default_callback,
845 LDB_REQ_SET_LOCATION(req);
847 if (ret != LDB_SUCCESS) {
852 ret = ldb_request_add_control(req,
853 DSDB_CONTROL_CURRENT_PARTITION_OID,
855 if (ret != LDB_SUCCESS) {
860 /* Run the new request */
861 ret = ldb_next_request(module, req);
863 if (ret == LDB_SUCCESS) {
864 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
866 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
867 ret = ldb_build_add_req(&req, ldb, msg,
871 ldb_modify_default_callback,
873 LDB_REQ_SET_LOCATION(req);
882 bool dsdb_module_am_system(struct ldb_module *module)
884 struct ldb_context *ldb = ldb_module_get_ctx(module);
885 struct auth_session_info *session_info
886 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
887 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
890 bool dsdb_module_am_administrator(struct ldb_module *module)
892 struct ldb_context *ldb = ldb_module_get_ctx(module);
893 struct auth_session_info *session_info
894 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
895 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
899 check if the recyclebin is enabled
901 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
903 struct ldb_context *ldb = ldb_module_get_ctx(module);
904 struct ldb_dn *partitions_dn;
905 struct GUID recyclebin_guid;
908 partitions_dn = samdb_partitions_dn(ldb, module);
910 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
912 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
913 if (ret != LDB_SUCCESS) {
914 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
915 talloc_free(partitions_dn);
916 return LDB_ERR_UNWILLING_TO_PERFORM;
919 talloc_free(partitions_dn);
923 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
924 struct ldb_message *msg,
926 const int32_t *old_val,
927 const int32_t *new_val)
929 struct ldb_message_element *el;
934 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
935 if (ret != LDB_SUCCESS) {
939 el->values = talloc_array(msg, struct ldb_val, el->num_values);
941 return ldb_module_oom(module);
943 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
945 return ldb_module_oom(module);
947 *el->values = data_blob_string_const(vstring);
951 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
952 if (ret != LDB_SUCCESS) {
956 el->values = talloc_array(msg, struct ldb_val, el->num_values);
958 return ldb_module_oom(module);
960 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
962 return ldb_module_oom(module);
964 *el->values = data_blob_string_const(vstring);
970 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
971 struct ldb_message *msg,
973 const uint32_t *old_val,
974 const uint32_t *new_val)
976 return dsdb_msg_constrainted_update_int32(module, msg, attr,
977 (const int32_t *)old_val,
978 (const int32_t *)new_val);
981 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
982 struct ldb_message *msg,
984 const int64_t *old_val,
985 const int64_t *new_val)
987 struct ldb_message_element *el;
992 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
993 if (ret != LDB_SUCCESS) {
997 el->values = talloc_array(msg, struct ldb_val, el->num_values);
999 return ldb_module_oom(module);
1001 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1003 return ldb_module_oom(module);
1005 *el->values = data_blob_string_const(vstring);
1009 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1010 if (ret != LDB_SUCCESS) {
1014 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1016 return ldb_module_oom(module);
1018 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1020 return ldb_module_oom(module);
1022 *el->values = data_blob_string_const(vstring);
1028 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1029 struct ldb_message *msg,
1031 const uint64_t *old_val,
1032 const uint64_t *new_val)
1034 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1035 (const int64_t *)old_val,
1036 (const int64_t *)new_val);
1040 update an int32 attribute safely via a constrained delete/add
1042 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1045 const int32_t *old_val,
1046 const int32_t *new_val,
1047 struct ldb_request *parent)
1049 struct ldb_message *msg;
1052 msg = ldb_msg_new(module);
1055 ret = dsdb_msg_constrainted_update_int32(module,
1059 if (ret != LDB_SUCCESS) {
1064 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1069 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1072 const uint32_t *old_val,
1073 const uint32_t *new_val,
1074 struct ldb_request *parent)
1076 return dsdb_module_constrainted_update_int32(module, dn, attr,
1077 (const int32_t *)old_val,
1078 (const int32_t *)new_val, parent);
1082 update an int64 attribute safely via a constrained delete/add
1084 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1087 const int64_t *old_val,
1088 const int64_t *new_val,
1089 struct ldb_request *parent)
1091 struct ldb_message *msg;
1094 msg = ldb_msg_new(module);
1097 ret = dsdb_msg_constrainted_update_int64(module,
1101 if (ret != LDB_SUCCESS) {
1106 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1111 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1114 const uint64_t *old_val,
1115 const uint64_t *new_val,
1116 struct ldb_request *parent)
1118 return dsdb_module_constrainted_update_int64(module, dn, attr,
1119 (const int64_t *)old_val,
1120 (const int64_t *)new_val,
1125 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1126 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1129 struct ldb_dn *new_dn;
1130 struct ldb_context *ldb = ldb_module_get_ctx(module);
1131 static const char *attrs[] = { "dSHeuristics", NULL };
1132 struct ldb_result *res;
1134 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1135 if (!ldb_dn_add_child_fmt(new_dn,
1136 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1137 talloc_free(new_dn);
1140 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1143 DSDB_FLAG_NEXT_MODULE,
1145 if (ret == LDB_SUCCESS && res->count == 1) {
1146 talloc_free(new_dn);
1147 return ldb_msg_find_ldb_val(res->msgs[0],
1150 talloc_free(new_dn);
1154 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1156 TALLOC_CTX *tmp_ctx = talloc_new(module);
1158 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1160 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1162 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1168 talloc_free(tmp_ctx);
1172 bool dsdb_user_password_support(struct ldb_module *module,
1173 TALLOC_CTX *mem_ctx,
1174 struct ldb_request *parent)
1176 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1178 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1181 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1183 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1184 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1190 talloc_free(tmp_ctx);
1195 show the chain of requests, useful for debugging async requests
1197 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1199 char *s = ldb_module_call_chain(req, req);
1200 DEBUG(level, ("%s\n", s));
1205 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1206 * performing a modify operation.
1208 * In order that the constraint checking by the "objectclass_attrs" LDB module
1209 * does work properly, the change request should remain similar or only be
1210 * enhanced (no other modifications as deletions, variations).
1212 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1213 const char *attr_name,
1214 enum ldb_request_type operation)
1216 struct ldb_message_element *el = NULL;
1219 /* We've to walk over all modification entries and consider the last
1220 * non-delete one which belongs to "attr_name".
1222 * If "el" is NULL afterwards then that means there was no interesting
1224 for (i = 0; i < msg->num_elements; i++) {
1225 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1226 if ((operation == LDB_MODIFY) &&
1227 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1228 == LDB_FLAG_MOD_DELETE)) {
1231 el = &msg->elements[i];