2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 2009
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7 Copyright (C) Matthieu Patou <mat@matws.net> 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "ldb_module.h"
26 #include "librpc/ndr/libndr.h"
27 #include "dsdb/samdb/ldb_modules/util.h"
28 #include "dsdb/samdb/samdb.h"
30 #include "libcli/security/security.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);
113 int dsdb_module_search_tree(struct ldb_module *module,
115 struct ldb_result **_res,
116 struct ldb_dn *basedn,
117 enum ldb_scope scope,
118 struct ldb_parse_tree *tree,
119 const char * const *attrs,
121 struct ldb_request *parent)
124 struct ldb_request *req;
126 struct ldb_result *res;
128 tmp_ctx = talloc_new(mem_ctx);
130 /* cross-partitions searches with a basedn break multi-domain support */
131 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
133 res = talloc_zero(tmp_ctx, struct ldb_result);
135 talloc_free(tmp_ctx);
136 return ldb_oom(ldb_module_get_ctx(module));
139 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
146 ldb_search_default_callback,
148 LDB_REQ_SET_LOCATION(req);
149 if (ret != LDB_SUCCESS) {
150 talloc_free(tmp_ctx);
154 ret = dsdb_request_add_controls(req, dsdb_flags);
155 if (ret != LDB_SUCCESS) {
156 talloc_free(tmp_ctx);
160 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
161 ldb_req_mark_trusted(req);
164 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
165 ret = ldb_next_request(module, req);
166 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
167 ret = ldb_request(ldb_module_get_ctx(module), req);
169 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
170 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
171 ret = ops->search(module, req);
173 if (ret == LDB_SUCCESS) {
174 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
178 if (ret == LDB_SUCCESS) {
179 *_res = talloc_steal(mem_ctx, res);
181 talloc_free(tmp_ctx);
186 search for attrs in the modules below
188 int dsdb_module_search(struct ldb_module *module,
190 struct ldb_result **_res,
191 struct ldb_dn *basedn, enum ldb_scope scope,
192 const char * const *attrs,
194 struct ldb_request *parent,
195 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
201 struct ldb_parse_tree *tree;
203 /* cross-partitions searches with a basedn break multi-domain support */
204 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
206 tmp_ctx = talloc_new(mem_ctx);
209 va_start(ap, format);
210 expression = talloc_vasprintf(tmp_ctx, format, ap);
214 talloc_free(tmp_ctx);
215 return ldb_oom(ldb_module_get_ctx(module));
221 tree = ldb_parse_tree(tmp_ctx, expression);
223 talloc_free(tmp_ctx);
224 ldb_set_errstring(ldb_module_get_ctx(module),
225 "Unable to parse search expression");
226 return LDB_ERR_OPERATIONS_ERROR;
229 ret = dsdb_module_search_tree(module,
239 talloc_free(tmp_ctx);
244 find a DN given a GUID. This searches across all partitions
246 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
247 const struct GUID *guid, struct ldb_dn **dn,
248 struct ldb_request *parent)
250 struct ldb_result *res;
251 const char *attrs[] = { NULL };
252 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
255 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
257 DSDB_FLAG_NEXT_MODULE |
258 DSDB_SEARCH_SHOW_RECYCLED |
259 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
260 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
262 "objectGUID=%s", GUID_string(tmp_ctx, guid));
263 if (ret != LDB_SUCCESS) {
264 talloc_free(tmp_ctx);
267 if (res->count == 0) {
268 talloc_free(tmp_ctx);
269 return LDB_ERR_NO_SUCH_OBJECT;
271 if (res->count != 1) {
272 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
273 GUID_string(tmp_ctx, guid));
274 talloc_free(tmp_ctx);
275 return LDB_ERR_OPERATIONS_ERROR;
278 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
280 talloc_free(tmp_ctx);
285 find a GUID given a DN.
287 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
288 struct ldb_request *parent)
290 const char *attrs[] = { NULL };
291 struct ldb_result *res;
292 TALLOC_CTX *tmp_ctx = talloc_new(module);
296 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
297 DSDB_FLAG_NEXT_MODULE |
298 DSDB_SEARCH_SHOW_RECYCLED |
299 DSDB_SEARCH_SHOW_EXTENDED_DN,
301 if (ret != LDB_SUCCESS) {
302 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
303 ldb_dn_get_linearized(dn));
304 talloc_free(tmp_ctx);
308 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
309 if (!NT_STATUS_IS_OK(status)) {
310 talloc_free(tmp_ctx);
311 return ldb_operr(ldb_module_get_ctx(module));
314 talloc_free(tmp_ctx);
318 a ldb_extended request operating on modules below the
321 int dsdb_module_extended(struct ldb_module *module,
322 const char* oid, void* data,
324 struct ldb_request *parent)
326 struct ldb_request *req;
328 struct ldb_context *ldb = ldb_module_get_ctx(module);
329 TALLOC_CTX *tmp_ctx = talloc_new(module);
330 struct ldb_result *res;
332 res = talloc_zero(tmp_ctx, struct ldb_result);
334 talloc_free(tmp_ctx);
335 return ldb_oom(ldb_module_get_ctx(module));
338 ret = ldb_build_extended_req(&req, ldb,
343 res, ldb_extended_default_callback,
346 LDB_REQ_SET_LOCATION(req);
347 if (ret != LDB_SUCCESS) {
348 talloc_free(tmp_ctx);
352 ret = dsdb_request_add_controls(req, dsdb_flags);
353 if (ret != LDB_SUCCESS) {
354 talloc_free(tmp_ctx);
358 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
359 ldb_req_mark_trusted(req);
362 /* Run the new request */
363 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
364 ret = ldb_next_request(module, req);
365 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
366 ret = ldb_request(ldb_module_get_ctx(module), req);
368 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
369 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
370 ret = ops->extended(module, req);
372 if (ret == LDB_SUCCESS) {
373 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
376 talloc_free(tmp_ctx);
380 a ldb_modify request operating on modules below the
383 int dsdb_module_modify(struct ldb_module *module,
384 const struct ldb_message *message,
386 struct ldb_request *parent)
388 struct ldb_request *mod_req;
390 struct ldb_context *ldb = ldb_module_get_ctx(module);
391 TALLOC_CTX *tmp_ctx = talloc_new(module);
392 struct ldb_result *res;
394 res = talloc_zero(tmp_ctx, struct ldb_result);
396 talloc_free(tmp_ctx);
397 return ldb_oom(ldb_module_get_ctx(module));
400 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
404 ldb_modify_default_callback,
406 LDB_REQ_SET_LOCATION(mod_req);
407 if (ret != LDB_SUCCESS) {
408 talloc_free(tmp_ctx);
412 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
413 if (ret != LDB_SUCCESS) {
414 talloc_free(tmp_ctx);
418 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
419 ldb_req_mark_trusted(mod_req);
422 /* Run the new request */
423 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
424 ret = ldb_next_request(module, mod_req);
425 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
426 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
428 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
429 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
430 ret = ops->modify(module, mod_req);
432 if (ret == LDB_SUCCESS) {
433 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
436 talloc_free(tmp_ctx);
443 a ldb_rename request operating on modules below the
446 int dsdb_module_rename(struct ldb_module *module,
447 struct ldb_dn *olddn, struct ldb_dn *newdn,
449 struct ldb_request *parent)
451 struct ldb_request *req;
453 struct ldb_context *ldb = ldb_module_get_ctx(module);
454 TALLOC_CTX *tmp_ctx = talloc_new(module);
455 struct ldb_result *res;
457 res = talloc_zero(tmp_ctx, struct ldb_result);
459 talloc_free(tmp_ctx);
460 return ldb_oom(ldb_module_get_ctx(module));
463 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
468 ldb_modify_default_callback,
470 LDB_REQ_SET_LOCATION(req);
471 if (ret != LDB_SUCCESS) {
472 talloc_free(tmp_ctx);
476 ret = dsdb_request_add_controls(req, dsdb_flags);
477 if (ret != LDB_SUCCESS) {
478 talloc_free(tmp_ctx);
482 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
483 ldb_req_mark_trusted(req);
486 /* Run the new request */
487 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
488 ret = ldb_next_request(module, req);
489 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
490 ret = ldb_request(ldb_module_get_ctx(module), req);
492 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
493 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
494 ret = ops->rename(module, req);
496 if (ret == LDB_SUCCESS) {
497 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
500 talloc_free(tmp_ctx);
505 a ldb_add request operating on modules below the
508 int dsdb_module_add(struct ldb_module *module,
509 const struct ldb_message *message,
511 struct ldb_request *parent)
513 struct ldb_request *req;
515 struct ldb_context *ldb = ldb_module_get_ctx(module);
516 TALLOC_CTX *tmp_ctx = talloc_new(module);
517 struct ldb_result *res;
519 res = talloc_zero(tmp_ctx, struct ldb_result);
521 talloc_free(tmp_ctx);
522 return ldb_oom(ldb_module_get_ctx(module));
525 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
529 ldb_modify_default_callback,
531 LDB_REQ_SET_LOCATION(req);
532 if (ret != LDB_SUCCESS) {
533 talloc_free(tmp_ctx);
537 ret = dsdb_request_add_controls(req, dsdb_flags);
538 if (ret != LDB_SUCCESS) {
539 talloc_free(tmp_ctx);
543 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
544 ldb_req_mark_trusted(req);
547 /* Run the new request */
548 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
549 ret = ldb_next_request(module, req);
550 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
551 ret = ldb_request(ldb_module_get_ctx(module), req);
553 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
554 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
555 ret = ops->add(module, req);
557 if (ret == LDB_SUCCESS) {
558 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
561 talloc_free(tmp_ctx);
566 a ldb_delete request operating on modules below the
569 int dsdb_module_del(struct ldb_module *module,
572 struct ldb_request *parent)
574 struct ldb_request *req;
576 struct ldb_context *ldb = ldb_module_get_ctx(module);
577 TALLOC_CTX *tmp_ctx = talloc_new(module);
578 struct ldb_result *res;
580 res = talloc_zero(tmp_ctx, struct ldb_result);
582 talloc_free(tmp_ctx);
586 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
590 ldb_modify_default_callback,
592 LDB_REQ_SET_LOCATION(req);
593 if (ret != LDB_SUCCESS) {
594 talloc_free(tmp_ctx);
598 ret = dsdb_request_add_controls(req, dsdb_flags);
599 if (ret != LDB_SUCCESS) {
600 talloc_free(tmp_ctx);
604 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
605 ldb_req_mark_trusted(req);
608 /* Run the new request */
609 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
610 ret = ldb_next_request(module, req);
611 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
612 ret = ldb_request(ldb_module_get_ctx(module), req);
614 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
615 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
616 ret = ops->del(module, req);
618 if (ret == LDB_SUCCESS) {
619 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
622 talloc_free(tmp_ctx);
627 check if a single valued link has multiple non-deleted values
629 This is needed when we will be using the RELAX control to stop
630 ldb_tdb from checking single valued links
632 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
633 const struct ldb_message_element *el)
635 bool found_active = false;
638 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
639 el->num_values < 2) {
643 for (i=0; i<el->num_values; i++) {
644 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
646 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
655 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
656 struct GUID op_feature_guid, bool *feature_enabled)
659 struct ldb_context *ldb = ldb_module_get_ctx(module);
660 struct ldb_result *res;
661 struct ldb_dn *search_dn;
662 struct GUID search_guid;
663 const char *attrs[] = {"msDS-EnabledFeature", NULL};
666 struct ldb_message_element *el;
668 *feature_enabled = false;
670 tmp_ctx = talloc_new(ldb);
672 ret = ldb_search(ldb, tmp_ctx, &res,
673 scope, LDB_SCOPE_BASE, attrs,
675 if (ret != LDB_SUCCESS) {
676 ldb_asprintf_errstring(ldb,
677 "Could no find the scope object - dn: %s\n",
678 ldb_dn_get_linearized(scope));
679 talloc_free(tmp_ctx);
680 return LDB_ERR_OPERATIONS_ERROR;
682 if (res->msgs[0]->num_elements > 0) {
684 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
686 attrs[0] = "msDS-OptionalFeatureGUID";
688 for (i=0; i<el->num_values; i++) {
689 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
691 ret = ldb_search(ldb, tmp_ctx, &res,
692 search_dn, LDB_SCOPE_BASE, attrs,
694 if (ret != LDB_SUCCESS) {
695 ldb_asprintf_errstring(ldb,
696 "Could no find object dn: %s\n",
697 ldb_dn_get_linearized(search_dn));
698 talloc_free(tmp_ctx);
699 return LDB_ERR_OPERATIONS_ERROR;
702 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
704 if (GUID_compare(&search_guid, &op_feature_guid) == 0){
705 *feature_enabled = true;
710 talloc_free(tmp_ctx);
715 find the NTDS GUID from a computers DN record
717 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
719 struct ldb_dn *computer_dn,
720 struct GUID *ntds_guid,
721 struct ldb_request *parent)
726 *ntds_guid = GUID_zero();
728 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
729 "serverReferenceBL", &dn, parent);
730 if (ret != LDB_SUCCESS) {
734 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
736 return LDB_ERR_OPERATIONS_ERROR;
739 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
745 find a 'reference' DN that points at another object
746 (eg. serverReference, rIDManagerReference etc)
748 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
749 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
751 const char *attrs[2];
752 struct ldb_result *res;
755 attrs[0] = attribute;
758 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
759 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
760 if (ret != LDB_SUCCESS) {
764 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
765 mem_ctx, res->msgs[0], attribute);
767 ldb_reset_err_string(ldb_module_get_ctx(module));
769 return LDB_ERR_NO_SUCH_ATTRIBUTE;
777 find the RID Manager$ DN via the rIDManagerReference attribute in the
780 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
781 struct ldb_request *parent)
783 return dsdb_module_reference_dn(module, mem_ctx,
784 ldb_get_default_basedn(ldb_module_get_ctx(module)),
785 "rIDManagerReference", dn, parent);
789 used to chain to the callers callback
791 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
793 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
795 talloc_steal(up_req, req);
796 return up_req->callback(up_req, ares);
800 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
801 object for a partition
803 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
804 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
806 struct ldb_context *ldb = ldb_module_get_ctx(module);
807 struct ldb_request *req;
809 TALLOC_CTX *tmp_ctx = talloc_new(module);
810 struct dsdb_control_current_partition *p_ctrl;
811 struct ldb_result *res;
813 res = talloc_zero(tmp_ctx, struct ldb_result);
815 talloc_free(tmp_ctx);
816 return ldb_module_oom(module);
819 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
820 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
824 res, ldb_search_default_callback,
826 LDB_REQ_SET_LOCATION(req);
827 if (ret != LDB_SUCCESS) {
828 talloc_free(tmp_ctx);
832 p_ctrl = talloc(req, struct dsdb_control_current_partition);
833 if (p_ctrl == NULL) {
834 talloc_free(tmp_ctx);
835 return ldb_module_oom(module);
837 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
841 ret = ldb_request_add_control(req,
842 DSDB_CONTROL_CURRENT_PARTITION_OID,
844 if (ret != LDB_SUCCESS) {
845 talloc_free(tmp_ctx);
849 /* Run the new request */
850 ret = ldb_next_request(module, req);
852 if (ret == LDB_SUCCESS) {
853 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
856 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
857 /* it hasn't been created yet, which means
858 an implicit value of zero */
860 talloc_free(tmp_ctx);
861 ldb_reset_err_string(ldb);
865 if (ret != LDB_SUCCESS) {
866 talloc_free(tmp_ctx);
870 if (res->count != 1) {
876 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
878 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
882 talloc_free(tmp_ctx);
888 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
891 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
892 uint64_t uSN, uint64_t urgent_uSN,
893 struct ldb_request *parent)
895 struct ldb_context *ldb = ldb_module_get_ctx(module);
896 struct ldb_request *req;
897 struct ldb_message *msg;
898 struct dsdb_control_current_partition *p_ctrl;
900 struct ldb_result *res;
902 msg = ldb_msg_new(module);
904 return ldb_module_oom(module);
907 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
908 if (msg->dn == NULL) {
910 return ldb_operr(ldb_module_get_ctx(module));
913 res = talloc_zero(msg, struct ldb_result);
916 return ldb_module_oom(module);
919 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
920 if (ret != LDB_SUCCESS) {
924 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
926 /* urgent_uSN is optional so may not be stored */
928 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
930 if (ret != LDB_SUCCESS) {
934 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
938 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
939 if (p_ctrl == NULL) {
943 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
945 ret = ldb_build_mod_req(&req, ldb, msg,
949 ldb_modify_default_callback,
951 LDB_REQ_SET_LOCATION(req);
953 if (ret != LDB_SUCCESS) {
958 ret = ldb_request_add_control(req,
959 DSDB_CONTROL_CURRENT_PARTITION_OID,
961 if (ret != LDB_SUCCESS) {
966 /* Run the new request */
967 ret = ldb_next_request(module, req);
969 if (ret == LDB_SUCCESS) {
970 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
972 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
973 ret = ldb_build_add_req(&req, ldb, msg,
977 ldb_modify_default_callback,
979 LDB_REQ_SET_LOCATION(req);
988 bool dsdb_module_am_system(struct ldb_module *module)
990 struct ldb_context *ldb = ldb_module_get_ctx(module);
991 struct auth_session_info *session_info
992 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
993 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
996 bool dsdb_module_am_administrator(struct ldb_module *module)
998 struct ldb_context *ldb = ldb_module_get_ctx(module);
999 struct auth_session_info *session_info
1000 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1001 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1005 check if the recyclebin is enabled
1007 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1009 struct ldb_context *ldb = ldb_module_get_ctx(module);
1010 struct ldb_dn *partitions_dn;
1011 struct GUID recyclebin_guid;
1014 partitions_dn = samdb_partitions_dn(ldb, module);
1016 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1018 ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
1019 if (ret != LDB_SUCCESS) {
1020 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1021 talloc_free(partitions_dn);
1022 return LDB_ERR_UNWILLING_TO_PERFORM;
1025 talloc_free(partitions_dn);
1029 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1030 struct ldb_message *msg,
1032 const int32_t *old_val,
1033 const int32_t *new_val)
1035 struct ldb_message_element *el;
1040 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1041 if (ret != LDB_SUCCESS) {
1045 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1047 return ldb_module_oom(module);
1049 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1051 return ldb_module_oom(module);
1053 *el->values = data_blob_string_const(vstring);
1057 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1058 if (ret != LDB_SUCCESS) {
1062 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1064 return ldb_module_oom(module);
1066 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1068 return ldb_module_oom(module);
1070 *el->values = data_blob_string_const(vstring);
1076 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1077 struct ldb_message *msg,
1079 const uint32_t *old_val,
1080 const uint32_t *new_val)
1082 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1083 (const int32_t *)old_val,
1084 (const int32_t *)new_val);
1087 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1088 struct ldb_message *msg,
1090 const int64_t *old_val,
1091 const int64_t *new_val)
1093 struct ldb_message_element *el;
1098 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1099 if (ret != LDB_SUCCESS) {
1103 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1105 return ldb_module_oom(module);
1107 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1109 return ldb_module_oom(module);
1111 *el->values = data_blob_string_const(vstring);
1115 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1116 if (ret != LDB_SUCCESS) {
1120 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1122 return ldb_module_oom(module);
1124 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1126 return ldb_module_oom(module);
1128 *el->values = data_blob_string_const(vstring);
1134 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1135 struct ldb_message *msg,
1137 const uint64_t *old_val,
1138 const uint64_t *new_val)
1140 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1141 (const int64_t *)old_val,
1142 (const int64_t *)new_val);
1146 update an int32 attribute safely via a constrained delete/add
1148 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1151 const int32_t *old_val,
1152 const int32_t *new_val,
1153 struct ldb_request *parent)
1155 struct ldb_message *msg;
1158 msg = ldb_msg_new(module);
1161 ret = dsdb_msg_constrainted_update_int32(module,
1165 if (ret != LDB_SUCCESS) {
1170 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1175 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1178 const uint32_t *old_val,
1179 const uint32_t *new_val,
1180 struct ldb_request *parent)
1182 return dsdb_module_constrainted_update_int32(module, dn, attr,
1183 (const int32_t *)old_val,
1184 (const int32_t *)new_val, parent);
1188 update an int64 attribute safely via a constrained delete/add
1190 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1193 const int64_t *old_val,
1194 const int64_t *new_val,
1195 struct ldb_request *parent)
1197 struct ldb_message *msg;
1200 msg = ldb_msg_new(module);
1203 ret = dsdb_msg_constrainted_update_int64(module,
1207 if (ret != LDB_SUCCESS) {
1212 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1217 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1220 const uint64_t *old_val,
1221 const uint64_t *new_val,
1222 struct ldb_request *parent)
1224 return dsdb_module_constrainted_update_int64(module, dn, attr,
1225 (const int64_t *)old_val,
1226 (const int64_t *)new_val,
1231 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1232 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1235 struct ldb_dn *new_dn;
1236 struct ldb_context *ldb = ldb_module_get_ctx(module);
1237 static const char *attrs[] = { "dSHeuristics", NULL };
1238 struct ldb_result *res;
1240 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1241 if (!ldb_dn_add_child_fmt(new_dn,
1242 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1243 talloc_free(new_dn);
1246 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1249 DSDB_FLAG_NEXT_MODULE,
1251 if (ret == LDB_SUCCESS && res->count == 1) {
1252 talloc_free(new_dn);
1253 return ldb_msg_find_ldb_val(res->msgs[0],
1256 talloc_free(new_dn);
1260 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1262 TALLOC_CTX *tmp_ctx = talloc_new(module);
1264 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1266 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1268 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1274 talloc_free(tmp_ctx);
1278 bool dsdb_user_password_support(struct ldb_module *module,
1279 TALLOC_CTX *mem_ctx,
1280 struct ldb_request *parent)
1282 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1284 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1287 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1289 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1290 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1296 talloc_free(tmp_ctx);
1301 show the chain of requests, useful for debugging async requests
1303 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1305 char *s = ldb_module_call_chain(req, req);
1306 DEBUG(level, ("%s\n", s));
1311 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1312 * performing a modify operation.
1314 * In order that the constraint checking by the "objectclass_attrs" LDB module
1315 * does work properly, the change request should remain similar or only be
1316 * enhanced (no other modifications as deletions, variations).
1318 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1319 const char *attr_name,
1320 enum ldb_request_type operation)
1322 struct ldb_message_element *el = NULL;
1325 /* We've to walk over all modification entries and consider the last
1326 * non-delete one which belongs to "attr_name".
1328 * If "el" is NULL afterwards then that means there was no interesting
1330 for (i = 0; i < msg->num_elements; i++) {
1331 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1332 if ((operation == LDB_MODIFY) &&
1333 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1334 == LDB_FLAG_MOD_DELETE)) {
1337 el = &msg->elements[i];