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"
29 #include "dsdb/common/util.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;
656 check if an optional feature is enabled on our own NTDS DN
658 Note that features can be marked as enabled in more than one
659 place. For example, the recyclebin feature is marked as enabled both
660 on the CN=Partitions,CN=Configurration object and on the NTDS DN of
661 each DC in the forest. It seems likely that it is the job of the KCC
662 to propogate between the two
664 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
667 struct ldb_context *ldb = ldb_module_get_ctx(module);
668 struct ldb_result *res;
669 struct ldb_dn *search_dn;
670 struct GUID search_guid;
671 const char *attrs[] = {"msDS-EnabledFeature", NULL};
674 struct ldb_message_element *el;
675 struct ldb_dn *feature_dn;
677 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module));
678 if (feature_dn == NULL) {
679 return ldb_operr(ldb_module_get_ctx(module));
682 *feature_enabled = false;
684 tmp_ctx = talloc_new(ldb);
686 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
687 if (ret != LDB_SUCCESS) {
688 ldb_asprintf_errstring(ldb,
689 "Could not find the feature object - dn: %s\n",
690 ldb_dn_get_linearized(feature_dn));
691 talloc_free(tmp_ctx);
692 return LDB_ERR_OPERATIONS_ERROR;
694 if (res->msgs[0]->num_elements > 0) {
695 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
697 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
699 for (i=0; i<el->num_values; i++) {
700 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
702 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
703 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
704 if (ret != LDB_SUCCESS) {
705 ldb_asprintf_errstring(ldb,
706 "Could no find object dn: %s\n",
707 ldb_dn_get_linearized(search_dn));
708 talloc_free(tmp_ctx);
709 return LDB_ERR_OPERATIONS_ERROR;
712 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
714 if (GUID_compare(&search_guid, &op_feature_guid) == 0) {
715 *feature_enabled = true;
720 talloc_free(tmp_ctx);
725 find the NTDS GUID from a computers DN record
727 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
729 struct ldb_dn *computer_dn,
730 struct GUID *ntds_guid,
731 struct ldb_request *parent)
736 *ntds_guid = GUID_zero();
738 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
739 "serverReferenceBL", &dn, parent);
740 if (ret != LDB_SUCCESS) {
744 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
746 return LDB_ERR_OPERATIONS_ERROR;
749 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
755 find a 'reference' DN that points at another object
756 (eg. serverReference, rIDManagerReference etc)
758 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
759 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
761 const char *attrs[2];
762 struct ldb_result *res;
765 attrs[0] = attribute;
768 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
769 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
770 if (ret != LDB_SUCCESS) {
774 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
775 mem_ctx, res->msgs[0], attribute);
777 ldb_reset_err_string(ldb_module_get_ctx(module));
779 return LDB_ERR_NO_SUCH_ATTRIBUTE;
787 find the RID Manager$ DN via the rIDManagerReference attribute in the
790 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
791 struct ldb_request *parent)
793 return dsdb_module_reference_dn(module, mem_ctx,
794 ldb_get_default_basedn(ldb_module_get_ctx(module)),
795 "rIDManagerReference", dn, parent);
799 used to chain to the callers callback
801 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
803 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
805 talloc_steal(up_req, req);
806 return up_req->callback(up_req, ares);
810 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
811 object for a partition
813 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
814 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
816 struct ldb_context *ldb = ldb_module_get_ctx(module);
817 struct ldb_request *req;
819 TALLOC_CTX *tmp_ctx = talloc_new(module);
820 struct dsdb_control_current_partition *p_ctrl;
821 struct ldb_result *res;
823 res = talloc_zero(tmp_ctx, struct ldb_result);
825 talloc_free(tmp_ctx);
826 return ldb_module_oom(module);
829 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
830 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
834 res, ldb_search_default_callback,
836 LDB_REQ_SET_LOCATION(req);
837 if (ret != LDB_SUCCESS) {
838 talloc_free(tmp_ctx);
842 p_ctrl = talloc(req, struct dsdb_control_current_partition);
843 if (p_ctrl == NULL) {
844 talloc_free(tmp_ctx);
845 return ldb_module_oom(module);
847 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
851 ret = ldb_request_add_control(req,
852 DSDB_CONTROL_CURRENT_PARTITION_OID,
854 if (ret != LDB_SUCCESS) {
855 talloc_free(tmp_ctx);
859 /* Run the new request */
860 ret = ldb_next_request(module, req);
862 if (ret == LDB_SUCCESS) {
863 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
866 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
867 /* it hasn't been created yet, which means
868 an implicit value of zero */
870 talloc_free(tmp_ctx);
871 ldb_reset_err_string(ldb);
875 if (ret != LDB_SUCCESS) {
876 talloc_free(tmp_ctx);
880 if (res->count != 1) {
886 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
888 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
892 talloc_free(tmp_ctx);
898 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
901 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
902 uint64_t uSN, uint64_t urgent_uSN,
903 struct ldb_request *parent)
905 struct ldb_context *ldb = ldb_module_get_ctx(module);
906 struct ldb_request *req;
907 struct ldb_message *msg;
908 struct dsdb_control_current_partition *p_ctrl;
910 struct ldb_result *res;
912 msg = ldb_msg_new(module);
914 return ldb_module_oom(module);
917 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
918 if (msg->dn == NULL) {
920 return ldb_operr(ldb_module_get_ctx(module));
923 res = talloc_zero(msg, struct ldb_result);
926 return ldb_module_oom(module);
929 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
930 if (ret != LDB_SUCCESS) {
934 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
936 /* urgent_uSN is optional so may not be stored */
938 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
940 if (ret != LDB_SUCCESS) {
944 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
948 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
949 if (p_ctrl == NULL) {
953 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
955 ret = ldb_build_mod_req(&req, ldb, msg,
959 ldb_modify_default_callback,
961 LDB_REQ_SET_LOCATION(req);
963 if (ret != LDB_SUCCESS) {
968 ret = ldb_request_add_control(req,
969 DSDB_CONTROL_CURRENT_PARTITION_OID,
971 if (ret != LDB_SUCCESS) {
976 /* Run the new request */
977 ret = ldb_next_request(module, req);
979 if (ret == LDB_SUCCESS) {
980 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
982 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
983 ret = ldb_build_add_req(&req, ldb, msg,
987 ldb_modify_default_callback,
989 LDB_REQ_SET_LOCATION(req);
998 bool dsdb_module_am_system(struct ldb_module *module)
1000 struct ldb_context *ldb = ldb_module_get_ctx(module);
1001 struct auth_session_info *session_info
1002 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1003 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1006 bool dsdb_module_am_administrator(struct ldb_module *module)
1008 struct ldb_context *ldb = ldb_module_get_ctx(module);
1009 struct auth_session_info *session_info
1010 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1011 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1015 check if the recyclebin is enabled
1017 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1019 struct ldb_context *ldb = ldb_module_get_ctx(module);
1020 struct GUID recyclebin_guid;
1023 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1025 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1026 if (ret != LDB_SUCCESS) {
1027 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1028 return LDB_ERR_UNWILLING_TO_PERFORM;
1034 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1035 struct ldb_message *msg,
1037 const int32_t *old_val,
1038 const int32_t *new_val)
1040 struct ldb_message_element *el;
1045 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1046 if (ret != LDB_SUCCESS) {
1050 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1052 return ldb_module_oom(module);
1054 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1056 return ldb_module_oom(module);
1058 *el->values = data_blob_string_const(vstring);
1062 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1063 if (ret != LDB_SUCCESS) {
1067 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1069 return ldb_module_oom(module);
1071 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1073 return ldb_module_oom(module);
1075 *el->values = data_blob_string_const(vstring);
1081 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1082 struct ldb_message *msg,
1084 const uint32_t *old_val,
1085 const uint32_t *new_val)
1087 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1088 (const int32_t *)old_val,
1089 (const int32_t *)new_val);
1092 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1093 struct ldb_message *msg,
1095 const int64_t *old_val,
1096 const int64_t *new_val)
1098 struct ldb_message_element *el;
1103 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1104 if (ret != LDB_SUCCESS) {
1108 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1110 return ldb_module_oom(module);
1112 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1114 return ldb_module_oom(module);
1116 *el->values = data_blob_string_const(vstring);
1120 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1121 if (ret != LDB_SUCCESS) {
1125 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1127 return ldb_module_oom(module);
1129 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1131 return ldb_module_oom(module);
1133 *el->values = data_blob_string_const(vstring);
1139 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1140 struct ldb_message *msg,
1142 const uint64_t *old_val,
1143 const uint64_t *new_val)
1145 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1146 (const int64_t *)old_val,
1147 (const int64_t *)new_val);
1151 update an int32 attribute safely via a constrained delete/add
1153 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1156 const int32_t *old_val,
1157 const int32_t *new_val,
1158 struct ldb_request *parent)
1160 struct ldb_message *msg;
1163 msg = ldb_msg_new(module);
1166 ret = dsdb_msg_constrainted_update_int32(module,
1170 if (ret != LDB_SUCCESS) {
1175 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1180 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1183 const uint32_t *old_val,
1184 const uint32_t *new_val,
1185 struct ldb_request *parent)
1187 return dsdb_module_constrainted_update_int32(module, dn, attr,
1188 (const int32_t *)old_val,
1189 (const int32_t *)new_val, parent);
1193 update an int64 attribute safely via a constrained delete/add
1195 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1198 const int64_t *old_val,
1199 const int64_t *new_val,
1200 struct ldb_request *parent)
1202 struct ldb_message *msg;
1205 msg = ldb_msg_new(module);
1208 ret = dsdb_msg_constrainted_update_int64(module,
1212 if (ret != LDB_SUCCESS) {
1217 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1222 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1225 const uint64_t *old_val,
1226 const uint64_t *new_val,
1227 struct ldb_request *parent)
1229 return dsdb_module_constrainted_update_int64(module, dn, attr,
1230 (const int64_t *)old_val,
1231 (const int64_t *)new_val,
1236 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1237 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1240 struct ldb_dn *new_dn;
1241 struct ldb_context *ldb = ldb_module_get_ctx(module);
1242 static const char *attrs[] = { "dSHeuristics", NULL };
1243 struct ldb_result *res;
1245 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1246 if (!ldb_dn_add_child_fmt(new_dn,
1247 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1248 talloc_free(new_dn);
1251 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1254 DSDB_FLAG_NEXT_MODULE,
1256 if (ret == LDB_SUCCESS && res->count == 1) {
1257 talloc_free(new_dn);
1258 return ldb_msg_find_ldb_val(res->msgs[0],
1261 talloc_free(new_dn);
1265 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1267 TALLOC_CTX *tmp_ctx = talloc_new(module);
1269 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1271 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1273 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1279 talloc_free(tmp_ctx);
1283 bool dsdb_user_password_support(struct ldb_module *module,
1284 TALLOC_CTX *mem_ctx,
1285 struct ldb_request *parent)
1287 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1289 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1292 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1294 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1295 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1301 talloc_free(tmp_ctx);
1306 show the chain of requests, useful for debugging async requests
1308 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1310 char *s = ldb_module_call_chain(req, req);
1311 DEBUG(level, ("%s\n", s));
1316 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1317 * performing a modify operation.
1319 * In order that the constraint checking by the "objectclass_attrs" LDB module
1320 * does work properly, the change request should remain similar or only be
1321 * enhanced (no other modifications as deletions, variations).
1323 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1324 const char *attr_name,
1325 enum ldb_request_type operation)
1327 struct ldb_message_element *el = NULL;
1330 /* We've to walk over all modification entries and consider the last
1331 * non-delete one which belongs to "attr_name".
1333 * If "el" is NULL afterwards then that means there was no interesting
1335 for (i = 0; i < msg->num_elements; i++) {
1336 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1337 if ((operation == LDB_MODIFY) &&
1338 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1339 == LDB_FLAG_MOD_DELETE)) {
1342 el = &msg->elements[i];