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);
177 if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
178 if (res->count == 0) {
179 talloc_free(tmp_ctx);
180 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
182 if (res->count != 1) {
183 talloc_free(tmp_ctx);
184 ldb_reset_err_string(ldb_module_get_ctx(module));
185 return LDB_ERR_CONSTRAINT_VIOLATION;
190 if (ret == LDB_SUCCESS) {
191 *_res = talloc_steal(mem_ctx, res);
193 talloc_free(tmp_ctx);
198 search for attrs in the modules below
200 int dsdb_module_search(struct ldb_module *module,
202 struct ldb_result **_res,
203 struct ldb_dn *basedn, enum ldb_scope scope,
204 const char * const *attrs,
206 struct ldb_request *parent,
207 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
213 struct ldb_parse_tree *tree;
215 /* cross-partitions searches with a basedn break multi-domain support */
216 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
218 tmp_ctx = talloc_new(mem_ctx);
221 va_start(ap, format);
222 expression = talloc_vasprintf(tmp_ctx, format, ap);
226 talloc_free(tmp_ctx);
227 return ldb_oom(ldb_module_get_ctx(module));
233 tree = ldb_parse_tree(tmp_ctx, expression);
235 talloc_free(tmp_ctx);
236 ldb_set_errstring(ldb_module_get_ctx(module),
237 "Unable to parse search expression");
238 return LDB_ERR_OPERATIONS_ERROR;
241 ret = dsdb_module_search_tree(module,
251 talloc_free(tmp_ctx);
256 find a DN given a GUID. This searches across all partitions
258 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
259 const struct GUID *guid, struct ldb_dn **dn,
260 struct ldb_request *parent)
262 struct ldb_result *res;
263 const char *attrs[] = { NULL };
264 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
267 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
269 DSDB_FLAG_NEXT_MODULE |
270 DSDB_SEARCH_SHOW_RECYCLED |
271 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
272 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
274 "objectGUID=%s", GUID_string(tmp_ctx, guid));
275 if (ret != LDB_SUCCESS) {
276 talloc_free(tmp_ctx);
279 if (res->count == 0) {
280 talloc_free(tmp_ctx);
281 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
283 if (res->count != 1) {
284 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
285 GUID_string(tmp_ctx, guid));
286 talloc_free(tmp_ctx);
287 return LDB_ERR_OPERATIONS_ERROR;
290 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
292 talloc_free(tmp_ctx);
297 find a GUID given a DN.
299 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
300 struct ldb_request *parent)
302 const char *attrs[] = { NULL };
303 struct ldb_result *res;
304 TALLOC_CTX *tmp_ctx = talloc_new(module);
308 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
309 DSDB_FLAG_NEXT_MODULE |
310 DSDB_SEARCH_SHOW_RECYCLED |
311 DSDB_SEARCH_SHOW_EXTENDED_DN,
313 if (ret != LDB_SUCCESS) {
314 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
315 ldb_dn_get_linearized(dn));
316 talloc_free(tmp_ctx);
320 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
321 if (!NT_STATUS_IS_OK(status)) {
322 talloc_free(tmp_ctx);
323 return ldb_operr(ldb_module_get_ctx(module));
326 talloc_free(tmp_ctx);
332 a ldb_extended request operating on modules below the
335 Note that this does not automatically start a transaction. If you
336 need a transaction the caller needs to start it as needed.
338 int dsdb_module_extended(struct ldb_module *module,
340 struct ldb_result **_res,
341 const char* oid, void* data,
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;
355 res = talloc_zero(tmp_ctx, struct ldb_result);
357 talloc_free(tmp_ctx);
358 return ldb_oom(ldb_module_get_ctx(module));
361 ret = ldb_build_extended_req(&req, ldb,
366 res, ldb_extended_default_callback,
369 LDB_REQ_SET_LOCATION(req);
370 if (ret != LDB_SUCCESS) {
371 talloc_free(tmp_ctx);
375 ret = dsdb_request_add_controls(req, dsdb_flags);
376 if (ret != LDB_SUCCESS) {
377 talloc_free(tmp_ctx);
381 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
382 ldb_req_mark_trusted(req);
385 /* Run the new request */
386 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
387 ret = ldb_next_request(module, req);
388 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
389 ret = ldb_request(ldb_module_get_ctx(module), req);
391 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
392 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
393 ret = ops->extended(module, req);
395 if (ret == LDB_SUCCESS) {
396 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
399 if (_res != NULL && ret == LDB_SUCCESS) {
400 (*_res) = talloc_steal(mem_ctx, res);
403 talloc_free(tmp_ctx);
409 a ldb_modify request operating on modules below the
412 int dsdb_module_modify(struct ldb_module *module,
413 const struct ldb_message *message,
415 struct ldb_request *parent)
417 struct ldb_request *mod_req;
419 struct ldb_context *ldb = ldb_module_get_ctx(module);
420 TALLOC_CTX *tmp_ctx = talloc_new(module);
421 struct ldb_result *res;
423 res = talloc_zero(tmp_ctx, struct ldb_result);
425 talloc_free(tmp_ctx);
426 return ldb_oom(ldb_module_get_ctx(module));
429 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
433 ldb_modify_default_callback,
435 LDB_REQ_SET_LOCATION(mod_req);
436 if (ret != LDB_SUCCESS) {
437 talloc_free(tmp_ctx);
441 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
442 if (ret != LDB_SUCCESS) {
443 talloc_free(tmp_ctx);
447 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
448 ldb_req_mark_trusted(mod_req);
451 /* Run the new request */
452 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
453 ret = ldb_next_request(module, mod_req);
454 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
455 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
457 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
458 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
459 ret = ops->modify(module, mod_req);
461 if (ret == LDB_SUCCESS) {
462 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
465 talloc_free(tmp_ctx);
472 a ldb_rename request operating on modules below the
475 int dsdb_module_rename(struct ldb_module *module,
476 struct ldb_dn *olddn, struct ldb_dn *newdn,
478 struct ldb_request *parent)
480 struct ldb_request *req;
482 struct ldb_context *ldb = ldb_module_get_ctx(module);
483 TALLOC_CTX *tmp_ctx = talloc_new(module);
484 struct ldb_result *res;
486 res = talloc_zero(tmp_ctx, struct ldb_result);
488 talloc_free(tmp_ctx);
489 return ldb_oom(ldb_module_get_ctx(module));
492 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
497 ldb_modify_default_callback,
499 LDB_REQ_SET_LOCATION(req);
500 if (ret != LDB_SUCCESS) {
501 talloc_free(tmp_ctx);
505 ret = dsdb_request_add_controls(req, dsdb_flags);
506 if (ret != LDB_SUCCESS) {
507 talloc_free(tmp_ctx);
511 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
512 ldb_req_mark_trusted(req);
515 /* Run the new request */
516 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
517 ret = ldb_next_request(module, req);
518 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
519 ret = ldb_request(ldb_module_get_ctx(module), req);
521 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
522 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
523 ret = ops->rename(module, req);
525 if (ret == LDB_SUCCESS) {
526 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
529 talloc_free(tmp_ctx);
534 a ldb_add request operating on modules below the
537 int dsdb_module_add(struct ldb_module *module,
538 const struct ldb_message *message,
540 struct ldb_request *parent)
542 struct ldb_request *req;
544 struct ldb_context *ldb = ldb_module_get_ctx(module);
545 TALLOC_CTX *tmp_ctx = talloc_new(module);
546 struct ldb_result *res;
548 res = talloc_zero(tmp_ctx, struct ldb_result);
550 talloc_free(tmp_ctx);
551 return ldb_oom(ldb_module_get_ctx(module));
554 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
558 ldb_modify_default_callback,
560 LDB_REQ_SET_LOCATION(req);
561 if (ret != LDB_SUCCESS) {
562 talloc_free(tmp_ctx);
566 ret = dsdb_request_add_controls(req, dsdb_flags);
567 if (ret != LDB_SUCCESS) {
568 talloc_free(tmp_ctx);
572 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
573 ldb_req_mark_trusted(req);
576 /* Run the new request */
577 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
578 ret = ldb_next_request(module, req);
579 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
580 ret = ldb_request(ldb_module_get_ctx(module), req);
582 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
583 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
584 ret = ops->add(module, req);
586 if (ret == LDB_SUCCESS) {
587 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
590 talloc_free(tmp_ctx);
595 a ldb_delete request operating on modules below the
598 int dsdb_module_del(struct ldb_module *module,
601 struct ldb_request *parent)
603 struct ldb_request *req;
605 struct ldb_context *ldb = ldb_module_get_ctx(module);
606 TALLOC_CTX *tmp_ctx = talloc_new(module);
607 struct ldb_result *res;
609 res = talloc_zero(tmp_ctx, struct ldb_result);
611 talloc_free(tmp_ctx);
615 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
619 ldb_modify_default_callback,
621 LDB_REQ_SET_LOCATION(req);
622 if (ret != LDB_SUCCESS) {
623 talloc_free(tmp_ctx);
627 ret = dsdb_request_add_controls(req, dsdb_flags);
628 if (ret != LDB_SUCCESS) {
629 talloc_free(tmp_ctx);
633 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
634 ldb_req_mark_trusted(req);
637 /* Run the new request */
638 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
639 ret = ldb_next_request(module, req);
640 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
641 ret = ldb_request(ldb_module_get_ctx(module), req);
643 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
644 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
645 ret = ops->del(module, req);
647 if (ret == LDB_SUCCESS) {
648 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
651 talloc_free(tmp_ctx);
656 check if a single valued link has multiple non-deleted values
658 This is needed when we will be using the RELAX control to stop
659 ldb_tdb from checking single valued links
661 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
662 const struct ldb_message_element *el)
664 bool found_active = false;
667 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
668 el->num_values < 2) {
672 for (i=0; i<el->num_values; i++) {
673 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
675 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
685 check if an optional feature is enabled on our own NTDS DN
687 Note that features can be marked as enabled in more than one
688 place. For example, the recyclebin feature is marked as enabled both
689 on the CN=Partitions,CN=Configurration object and on the NTDS DN of
690 each DC in the forest. It seems likely that it is the job of the KCC
691 to propagate between the two
693 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
696 struct ldb_context *ldb = ldb_module_get_ctx(module);
697 struct ldb_result *res;
698 struct ldb_dn *search_dn;
699 struct GUID search_guid;
700 const char *attrs[] = {"msDS-EnabledFeature", NULL};
703 struct ldb_message_element *el;
704 struct ldb_dn *feature_dn;
706 tmp_ctx = talloc_new(ldb);
708 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
709 if (feature_dn == NULL) {
710 talloc_free(tmp_ctx);
711 return ldb_operr(ldb_module_get_ctx(module));
714 *feature_enabled = false;
716 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
717 if (ret != LDB_SUCCESS) {
718 ldb_asprintf_errstring(ldb,
719 "Could not find the feature object - dn: %s\n",
720 ldb_dn_get_linearized(feature_dn));
721 talloc_free(tmp_ctx);
722 return LDB_ERR_NO_SUCH_OBJECT;
724 if (res->msgs[0]->num_elements > 0) {
725 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
727 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
729 for (i=0; i<el->num_values; i++) {
730 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
732 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
733 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
734 if (ret != LDB_SUCCESS) {
735 ldb_asprintf_errstring(ldb,
736 "Could no find object dn: %s\n",
737 ldb_dn_get_linearized(search_dn));
738 talloc_free(tmp_ctx);
739 return LDB_ERR_OPERATIONS_ERROR;
742 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
744 if (GUID_equal(&search_guid, &op_feature_guid)) {
745 *feature_enabled = true;
750 talloc_free(tmp_ctx);
755 find the NTDS GUID from a computers DN record
757 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
759 struct ldb_dn *computer_dn,
760 struct GUID *ntds_guid,
761 struct ldb_request *parent)
766 *ntds_guid = GUID_zero();
768 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
769 "serverReferenceBL", &dn, parent);
770 if (ret != LDB_SUCCESS) {
774 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
776 return LDB_ERR_OPERATIONS_ERROR;
779 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
785 find a 'reference' DN that points at another object
786 (eg. serverReference, rIDManagerReference etc)
788 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
789 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
791 const char *attrs[2];
792 struct ldb_result *res;
795 attrs[0] = attribute;
798 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
799 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
800 if (ret != LDB_SUCCESS) {
804 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
805 mem_ctx, res->msgs[0], attribute);
807 ldb_reset_err_string(ldb_module_get_ctx(module));
809 return LDB_ERR_NO_SUCH_ATTRIBUTE;
817 find the RID Manager$ DN via the rIDManagerReference attribute in the
820 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
821 struct ldb_request *parent)
823 return dsdb_module_reference_dn(module, mem_ctx,
824 ldb_get_default_basedn(ldb_module_get_ctx(module)),
825 "rIDManagerReference", dn, parent);
829 used to chain to the callers callback
831 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
833 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
836 return ldb_module_done(up_req, NULL, NULL,
837 LDB_ERR_OPERATIONS_ERROR);
840 if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
841 return ldb_module_done(up_req, ares->controls,
842 ares->response, ares->error);
845 /* Otherwise pass on the callback */
846 switch (ares->type) {
847 case LDB_REPLY_ENTRY:
848 return ldb_module_send_entry(up_req, ares->message,
851 case LDB_REPLY_REFERRAL:
852 return ldb_module_send_referral(up_req,
856 return LDB_ERR_OPERATIONS_ERROR;
861 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
862 object for a partition
864 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
865 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
867 struct ldb_context *ldb = ldb_module_get_ctx(module);
868 struct ldb_request *req;
870 TALLOC_CTX *tmp_ctx = talloc_new(module);
871 struct dsdb_control_current_partition *p_ctrl;
872 struct ldb_result *res;
874 res = talloc_zero(tmp_ctx, struct ldb_result);
876 talloc_free(tmp_ctx);
877 return ldb_module_oom(module);
880 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
881 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
885 res, ldb_search_default_callback,
887 LDB_REQ_SET_LOCATION(req);
888 if (ret != LDB_SUCCESS) {
889 talloc_free(tmp_ctx);
893 p_ctrl = talloc(req, struct dsdb_control_current_partition);
894 if (p_ctrl == NULL) {
895 talloc_free(tmp_ctx);
896 return ldb_module_oom(module);
898 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
902 ret = ldb_request_add_control(req,
903 DSDB_CONTROL_CURRENT_PARTITION_OID,
905 if (ret != LDB_SUCCESS) {
906 talloc_free(tmp_ctx);
910 /* Run the new request */
911 ret = ldb_next_request(module, req);
913 if (ret == LDB_SUCCESS) {
914 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
917 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
918 /* it hasn't been created yet, which means
919 an implicit value of zero */
921 talloc_free(tmp_ctx);
922 ldb_reset_err_string(ldb);
926 if (ret != LDB_SUCCESS) {
927 talloc_free(tmp_ctx);
931 if (res->count != 1) {
937 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
939 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
943 talloc_free(tmp_ctx);
949 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
952 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
953 uint64_t uSN, uint64_t urgent_uSN,
954 struct ldb_request *parent)
956 struct ldb_context *ldb = ldb_module_get_ctx(module);
957 struct ldb_request *req;
958 struct ldb_message *msg;
959 struct dsdb_control_current_partition *p_ctrl;
961 struct ldb_result *res;
963 msg = ldb_msg_new(module);
965 return ldb_module_oom(module);
968 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
969 if (msg->dn == NULL) {
971 return ldb_operr(ldb_module_get_ctx(module));
974 res = talloc_zero(msg, struct ldb_result);
977 return ldb_module_oom(module);
980 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
981 if (ret != LDB_SUCCESS) {
985 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
987 /* urgent_uSN is optional so may not be stored */
989 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
991 if (ret != LDB_SUCCESS) {
995 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
999 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1000 if (p_ctrl == NULL) {
1002 return ldb_oom(ldb);
1004 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1006 ret = ldb_build_mod_req(&req, ldb, msg,
1010 ldb_modify_default_callback,
1012 LDB_REQ_SET_LOCATION(req);
1014 if (ret != LDB_SUCCESS) {
1019 ret = ldb_request_add_control(req,
1020 DSDB_CONTROL_CURRENT_PARTITION_OID,
1022 if (ret != LDB_SUCCESS) {
1027 /* Run the new request */
1028 ret = ldb_next_request(module, req);
1030 if (ret == LDB_SUCCESS) {
1031 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1033 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1034 ret = ldb_build_add_req(&req, ldb, msg,
1038 ldb_modify_default_callback,
1040 LDB_REQ_SET_LOCATION(req);
1049 bool dsdb_module_am_system(struct ldb_module *module)
1051 struct ldb_context *ldb = ldb_module_get_ctx(module);
1052 struct auth_session_info *session_info
1053 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1054 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1057 bool dsdb_module_am_administrator(struct ldb_module *module)
1059 struct ldb_context *ldb = ldb_module_get_ctx(module);
1060 struct auth_session_info *session_info
1061 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1062 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1066 check if the recyclebin is enabled
1068 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1070 struct ldb_context *ldb = ldb_module_get_ctx(module);
1071 struct GUID recyclebin_guid;
1074 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1076 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1077 if (ret != LDB_SUCCESS) {
1078 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1085 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1086 struct ldb_message *msg,
1088 const int32_t *old_val,
1089 const int32_t *new_val)
1091 struct ldb_message_element *el;
1096 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1097 if (ret != LDB_SUCCESS) {
1101 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1103 return ldb_module_oom(module);
1105 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1107 return ldb_module_oom(module);
1109 *el->values = data_blob_string_const(vstring);
1113 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1114 if (ret != LDB_SUCCESS) {
1118 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1120 return ldb_module_oom(module);
1122 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1124 return ldb_module_oom(module);
1126 *el->values = data_blob_string_const(vstring);
1132 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1133 struct ldb_message *msg,
1135 const uint32_t *old_val,
1136 const uint32_t *new_val)
1138 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1139 (const int32_t *)old_val,
1140 (const int32_t *)new_val);
1143 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1144 struct ldb_message *msg,
1146 const int64_t *old_val,
1147 const int64_t *new_val)
1149 struct ldb_message_element *el;
1154 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1155 if (ret != LDB_SUCCESS) {
1159 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1161 return ldb_module_oom(module);
1163 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1165 return ldb_module_oom(module);
1167 *el->values = data_blob_string_const(vstring);
1171 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1172 if (ret != LDB_SUCCESS) {
1176 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1178 return ldb_module_oom(module);
1180 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1182 return ldb_module_oom(module);
1184 *el->values = data_blob_string_const(vstring);
1190 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1191 struct ldb_message *msg,
1193 const uint64_t *old_val,
1194 const uint64_t *new_val)
1196 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1197 (const int64_t *)old_val,
1198 (const int64_t *)new_val);
1202 update an int32 attribute safely via a constrained delete/add
1204 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1207 const int32_t *old_val,
1208 const int32_t *new_val,
1209 struct ldb_request *parent)
1211 struct ldb_message *msg;
1214 msg = ldb_msg_new(module);
1216 return ldb_module_oom(module);
1220 ret = dsdb_msg_constrainted_update_int32(module,
1224 if (ret != LDB_SUCCESS) {
1229 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1234 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1237 const uint32_t *old_val,
1238 const uint32_t *new_val,
1239 struct ldb_request *parent)
1241 return dsdb_module_constrainted_update_int32(module, dn, attr,
1242 (const int32_t *)old_val,
1243 (const int32_t *)new_val, parent);
1247 update an int64 attribute safely via a constrained delete/add
1249 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1252 const int64_t *old_val,
1253 const int64_t *new_val,
1254 struct ldb_request *parent)
1256 struct ldb_message *msg;
1259 msg = ldb_msg_new(module);
1261 return ldb_module_oom(module);
1265 ret = dsdb_msg_constrainted_update_int64(module,
1269 if (ret != LDB_SUCCESS) {
1274 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1279 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1282 const uint64_t *old_val,
1283 const uint64_t *new_val,
1284 struct ldb_request *parent)
1286 return dsdb_module_constrainted_update_int64(module, dn, attr,
1287 (const int64_t *)old_val,
1288 (const int64_t *)new_val,
1293 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1294 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1297 struct ldb_dn *new_dn;
1298 struct ldb_context *ldb = ldb_module_get_ctx(module);
1299 static const char *attrs[] = { "dSHeuristics", NULL };
1300 struct ldb_result *res;
1302 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1303 if (!ldb_dn_add_child_fmt(new_dn,
1304 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1305 talloc_free(new_dn);
1308 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1311 DSDB_FLAG_NEXT_MODULE,
1313 if (ret == LDB_SUCCESS && res->count == 1) {
1314 talloc_free(new_dn);
1315 return ldb_msg_find_ldb_val(res->msgs[0],
1318 talloc_free(new_dn);
1322 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1324 TALLOC_CTX *tmp_ctx = talloc_new(module);
1326 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1328 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1330 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1336 talloc_free(tmp_ctx);
1340 bool dsdb_user_password_support(struct ldb_module *module,
1341 TALLOC_CTX *mem_ctx,
1342 struct ldb_request *parent)
1344 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1346 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1349 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1351 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1352 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1358 talloc_free(tmp_ctx);
1363 show the chain of requests, useful for debugging async requests
1365 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1367 char *s = ldb_module_call_chain(req, req);
1368 DEBUG(level, ("%s\n", s));
1373 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1374 * performing a modify operation.
1376 * In order that the constraint checking by the "objectclass_attrs" LDB module
1377 * does work properly, the change request should remain similar or only be
1378 * enhanced (no other modifications as deletions, variations).
1380 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1381 const char *attr_name,
1382 enum ldb_request_type operation)
1384 struct ldb_message_element *el = NULL;
1387 /* We've to walk over all modification entries and consider the last
1388 * non-delete one which belongs to "attr_name".
1390 * If "el" is NULL afterwards then that means there was no interesting
1392 for (i = 0; i < msg->num_elements; i++) {
1393 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1394 if ((operation == LDB_MODIFY) &&
1395 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1396 == LDB_FLAG_MOD_DELETE)) {
1399 el = &msg->elements[i];
1407 * This function determines the (last) structural or 88 object class of a passed
1408 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1409 * Without schema this does not work and hence NULL is returned.
1411 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1412 const struct ldb_message_element *element)
1414 const struct dsdb_class *last_class;
1416 if (schema == NULL) {
1420 if (element->num_values == 0) {
1424 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1425 &element->values[element->num_values-1]);
1426 if (last_class == NULL) {
1429 if (last_class->objectClassCategory > 1) {
1436 const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1437 const struct ldb_message *msg)
1439 struct ldb_message_element *oc_el;
1441 oc_el = ldb_msg_find_element(msg, "objectClass");
1446 return dsdb_get_last_structural_class(schema, oc_el);
1449 /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1450 cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
1451 CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
1453 int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1456 char *upper_rdn_attr;
1458 for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1459 /* We need the attribute name in upper case */
1460 upper_rdn_attr = strupper_talloc(dn,
1461 ldb_dn_get_component_name(dn, i));
1462 if (!upper_rdn_attr) {
1463 return ldb_oom(ldb);
1465 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1466 *ldb_dn_get_component_val(dn, i));
1467 talloc_free(upper_rdn_attr);
1468 if (ret != LDB_SUCCESS) {
1476 * Make most specific objectCategory for the objectClass of passed object
1477 * NOTE: In this implementation we count that it is called on already
1478 * verified objectClass attribute value. See objectclass.c thorough
1479 * implementation for all the magic that involves
1481 * @param ldb ldb context
1482 * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1483 * Hence leave the responsibility to the caller.
1484 * @param obj AD object to determint objectCategory for
1485 * @param mem_ctx Memory context - usually it is obj actually
1486 * @param pobjectcategory location to store found objectCategory
1488 * @return LDB_SUCCESS or error including out of memory error
1490 int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1491 const struct ldb_message *obj,
1492 TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1494 const struct dsdb_class *objectclass;
1495 struct ldb_message_element *objectclass_element;
1496 struct dsdb_extended_dn_store_format *dn_format;
1498 objectclass_element = ldb_msg_find_element(obj, "objectClass");
1499 if (!objectclass_element) {
1500 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1501 ldb_dn_get_linearized(obj->dn));
1502 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1504 if (objectclass_element->num_values == 0) {
1505 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1506 ldb_dn_get_linearized(obj->dn));
1507 return LDB_ERR_CONSTRAINT_VIOLATION;
1511 * Get the new top-most structural object class and check for
1512 * unrelated structural classes
1514 objectclass = dsdb_get_last_structural_class(schema,
1515 objectclass_element);
1516 if (objectclass == NULL) {
1517 ldb_asprintf_errstring(ldb,
1518 "Failed to find a structural class for %s",
1519 ldb_dn_get_linearized(obj->dn));
1520 return LDB_ERR_UNWILLING_TO_PERFORM;
1523 dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1524 struct dsdb_extended_dn_store_format);
1525 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1526 /* Strip off extended components */
1527 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1528 objectclass->defaultObjectCategory);
1529 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1532 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1535 if (*pobjectcategory == NULL) {
1536 return ldb_oom(ldb);