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 ldb_reset_err_string(ldb_module_get_ctx(module));
181 return LDB_ERR_NO_SUCH_OBJECT;
183 if (res->count != 1) {
184 talloc_free(tmp_ctx);
185 ldb_reset_err_string(ldb_module_get_ctx(module));
186 return LDB_ERR_CONSTRAINT_VIOLATION;
191 if (ret == LDB_SUCCESS) {
192 *_res = talloc_steal(mem_ctx, res);
194 talloc_free(tmp_ctx);
199 search for attrs in the modules below
201 int dsdb_module_search(struct ldb_module *module,
203 struct ldb_result **_res,
204 struct ldb_dn *basedn, enum ldb_scope scope,
205 const char * const *attrs,
207 struct ldb_request *parent,
208 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
214 struct ldb_parse_tree *tree;
216 /* cross-partitions searches with a basedn break multi-domain support */
217 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
219 tmp_ctx = talloc_new(mem_ctx);
222 va_start(ap, format);
223 expression = talloc_vasprintf(tmp_ctx, format, ap);
227 talloc_free(tmp_ctx);
228 return ldb_oom(ldb_module_get_ctx(module));
234 tree = ldb_parse_tree(tmp_ctx, expression);
236 talloc_free(tmp_ctx);
237 ldb_set_errstring(ldb_module_get_ctx(module),
238 "Unable to parse search expression");
239 return LDB_ERR_OPERATIONS_ERROR;
242 ret = dsdb_module_search_tree(module,
252 talloc_free(tmp_ctx);
257 find a DN given a GUID. This searches across all partitions
259 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
260 const struct GUID *guid, struct ldb_dn **dn,
261 struct ldb_request *parent)
263 struct ldb_result *res;
264 const char *attrs[] = { NULL };
265 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
268 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
270 DSDB_FLAG_NEXT_MODULE |
271 DSDB_SEARCH_SHOW_RECYCLED |
272 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
273 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
275 "objectGUID=%s", GUID_string(tmp_ctx, guid));
276 if (ret != LDB_SUCCESS) {
277 talloc_free(tmp_ctx);
280 if (res->count == 0) {
281 talloc_free(tmp_ctx);
282 return LDB_ERR_NO_SUCH_OBJECT;
284 if (res->count != 1) {
285 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
286 GUID_string(tmp_ctx, guid));
287 talloc_free(tmp_ctx);
288 return LDB_ERR_OPERATIONS_ERROR;
291 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
293 talloc_free(tmp_ctx);
298 find a GUID given a DN.
300 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
301 struct ldb_request *parent)
303 const char *attrs[] = { NULL };
304 struct ldb_result *res;
305 TALLOC_CTX *tmp_ctx = talloc_new(module);
309 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
310 DSDB_FLAG_NEXT_MODULE |
311 DSDB_SEARCH_SHOW_RECYCLED |
312 DSDB_SEARCH_SHOW_EXTENDED_DN,
314 if (ret != LDB_SUCCESS) {
315 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
316 ldb_dn_get_linearized(dn));
317 talloc_free(tmp_ctx);
321 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
322 if (!NT_STATUS_IS_OK(status)) {
323 talloc_free(tmp_ctx);
324 return ldb_operr(ldb_module_get_ctx(module));
327 talloc_free(tmp_ctx);
333 a ldb_extended request operating on modules below the
336 Note that this does not automatically start a transaction. If you
337 need a transaction the caller needs to start it as needed.
339 int dsdb_module_extended(struct ldb_module *module,
341 struct ldb_result **_res,
342 const char* oid, void* data,
344 struct ldb_request *parent)
346 struct ldb_request *req;
348 struct ldb_context *ldb = ldb_module_get_ctx(module);
349 TALLOC_CTX *tmp_ctx = talloc_new(module);
350 struct ldb_result *res;
356 res = talloc_zero(tmp_ctx, struct ldb_result);
358 talloc_free(tmp_ctx);
359 return ldb_oom(ldb_module_get_ctx(module));
362 ret = ldb_build_extended_req(&req, ldb,
367 res, ldb_extended_default_callback,
370 LDB_REQ_SET_LOCATION(req);
371 if (ret != LDB_SUCCESS) {
372 talloc_free(tmp_ctx);
376 ret = dsdb_request_add_controls(req, dsdb_flags);
377 if (ret != LDB_SUCCESS) {
378 talloc_free(tmp_ctx);
382 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
383 ldb_req_mark_trusted(req);
386 /* Run the new request */
387 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
388 ret = ldb_next_request(module, req);
389 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
390 ret = ldb_request(ldb_module_get_ctx(module), req);
392 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
393 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
394 ret = ops->extended(module, req);
396 if (ret == LDB_SUCCESS) {
397 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
400 if (_res != NULL && ret == LDB_SUCCESS) {
401 (*_res) = talloc_steal(mem_ctx, res);
404 talloc_free(tmp_ctx);
410 a ldb_modify request operating on modules below the
413 int dsdb_module_modify(struct ldb_module *module,
414 const struct ldb_message *message,
416 struct ldb_request *parent)
418 struct ldb_request *mod_req;
420 struct ldb_context *ldb = ldb_module_get_ctx(module);
421 TALLOC_CTX *tmp_ctx = talloc_new(module);
422 struct ldb_result *res;
424 res = talloc_zero(tmp_ctx, struct ldb_result);
426 talloc_free(tmp_ctx);
427 return ldb_oom(ldb_module_get_ctx(module));
430 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
434 ldb_modify_default_callback,
436 LDB_REQ_SET_LOCATION(mod_req);
437 if (ret != LDB_SUCCESS) {
438 talloc_free(tmp_ctx);
442 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
443 if (ret != LDB_SUCCESS) {
444 talloc_free(tmp_ctx);
448 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
449 ldb_req_mark_trusted(mod_req);
452 /* Run the new request */
453 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
454 ret = ldb_next_request(module, mod_req);
455 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
456 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
458 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
459 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
460 ret = ops->modify(module, mod_req);
462 if (ret == LDB_SUCCESS) {
463 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
466 talloc_free(tmp_ctx);
473 a ldb_rename request operating on modules below the
476 int dsdb_module_rename(struct ldb_module *module,
477 struct ldb_dn *olddn, struct ldb_dn *newdn,
479 struct ldb_request *parent)
481 struct ldb_request *req;
483 struct ldb_context *ldb = ldb_module_get_ctx(module);
484 TALLOC_CTX *tmp_ctx = talloc_new(module);
485 struct ldb_result *res;
487 res = talloc_zero(tmp_ctx, struct ldb_result);
489 talloc_free(tmp_ctx);
490 return ldb_oom(ldb_module_get_ctx(module));
493 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
498 ldb_modify_default_callback,
500 LDB_REQ_SET_LOCATION(req);
501 if (ret != LDB_SUCCESS) {
502 talloc_free(tmp_ctx);
506 ret = dsdb_request_add_controls(req, dsdb_flags);
507 if (ret != LDB_SUCCESS) {
508 talloc_free(tmp_ctx);
512 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
513 ldb_req_mark_trusted(req);
516 /* Run the new request */
517 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
518 ret = ldb_next_request(module, req);
519 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
520 ret = ldb_request(ldb_module_get_ctx(module), req);
522 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
523 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
524 ret = ops->rename(module, req);
526 if (ret == LDB_SUCCESS) {
527 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
530 talloc_free(tmp_ctx);
535 a ldb_add request operating on modules below the
538 int dsdb_module_add(struct ldb_module *module,
539 const struct ldb_message *message,
541 struct ldb_request *parent)
543 struct ldb_request *req;
545 struct ldb_context *ldb = ldb_module_get_ctx(module);
546 TALLOC_CTX *tmp_ctx = talloc_new(module);
547 struct ldb_result *res;
549 res = talloc_zero(tmp_ctx, struct ldb_result);
551 talloc_free(tmp_ctx);
552 return ldb_oom(ldb_module_get_ctx(module));
555 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
559 ldb_modify_default_callback,
561 LDB_REQ_SET_LOCATION(req);
562 if (ret != LDB_SUCCESS) {
563 talloc_free(tmp_ctx);
567 ret = dsdb_request_add_controls(req, dsdb_flags);
568 if (ret != LDB_SUCCESS) {
569 talloc_free(tmp_ctx);
573 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
574 ldb_req_mark_trusted(req);
577 /* Run the new request */
578 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
579 ret = ldb_next_request(module, req);
580 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
581 ret = ldb_request(ldb_module_get_ctx(module), req);
583 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
584 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
585 ret = ops->add(module, req);
587 if (ret == LDB_SUCCESS) {
588 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
591 talloc_free(tmp_ctx);
596 a ldb_delete request operating on modules below the
599 int dsdb_module_del(struct ldb_module *module,
602 struct ldb_request *parent)
604 struct ldb_request *req;
606 struct ldb_context *ldb = ldb_module_get_ctx(module);
607 TALLOC_CTX *tmp_ctx = talloc_new(module);
608 struct ldb_result *res;
610 res = talloc_zero(tmp_ctx, struct ldb_result);
612 talloc_free(tmp_ctx);
616 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
620 ldb_modify_default_callback,
622 LDB_REQ_SET_LOCATION(req);
623 if (ret != LDB_SUCCESS) {
624 talloc_free(tmp_ctx);
628 ret = dsdb_request_add_controls(req, dsdb_flags);
629 if (ret != LDB_SUCCESS) {
630 talloc_free(tmp_ctx);
634 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
635 ldb_req_mark_trusted(req);
638 /* Run the new request */
639 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
640 ret = ldb_next_request(module, req);
641 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
642 ret = ldb_request(ldb_module_get_ctx(module), req);
644 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
645 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
646 ret = ops->del(module, req);
648 if (ret == LDB_SUCCESS) {
649 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
652 talloc_free(tmp_ctx);
657 check if a single valued link has multiple non-deleted values
659 This is needed when we will be using the RELAX control to stop
660 ldb_tdb from checking single valued links
662 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
663 const struct ldb_message_element *el)
665 bool found_active = false;
668 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
669 el->num_values < 2) {
673 for (i=0; i<el->num_values; i++) {
674 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
676 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
686 check if an optional feature is enabled on our own NTDS DN
688 Note that features can be marked as enabled in more than one
689 place. For example, the recyclebin feature is marked as enabled both
690 on the CN=Partitions,CN=Configurration object and on the NTDS DN of
691 each DC in the forest. It seems likely that it is the job of the KCC
692 to propogate between the two
694 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
697 struct ldb_context *ldb = ldb_module_get_ctx(module);
698 struct ldb_result *res;
699 struct ldb_dn *search_dn;
700 struct GUID search_guid;
701 const char *attrs[] = {"msDS-EnabledFeature", NULL};
704 struct ldb_message_element *el;
705 struct ldb_dn *feature_dn;
707 tmp_ctx = talloc_new(ldb);
709 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
710 if (feature_dn == NULL) {
711 talloc_free(tmp_ctx);
712 return ldb_operr(ldb_module_get_ctx(module));
715 *feature_enabled = false;
717 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
718 if (ret != LDB_SUCCESS) {
719 ldb_asprintf_errstring(ldb,
720 "Could not find the feature object - dn: %s\n",
721 ldb_dn_get_linearized(feature_dn));
722 talloc_free(tmp_ctx);
723 return LDB_ERR_OPERATIONS_ERROR;
725 if (res->msgs[0]->num_elements > 0) {
726 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
728 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
730 for (i=0; i<el->num_values; i++) {
731 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
733 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
734 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
735 if (ret != LDB_SUCCESS) {
736 ldb_asprintf_errstring(ldb,
737 "Could no find object dn: %s\n",
738 ldb_dn_get_linearized(search_dn));
739 talloc_free(tmp_ctx);
740 return LDB_ERR_OPERATIONS_ERROR;
743 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
745 if (GUID_equal(&search_guid, &op_feature_guid)) {
746 *feature_enabled = true;
751 talloc_free(tmp_ctx);
756 find the NTDS GUID from a computers DN record
758 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
760 struct ldb_dn *computer_dn,
761 struct GUID *ntds_guid,
762 struct ldb_request *parent)
767 *ntds_guid = GUID_zero();
769 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
770 "serverReferenceBL", &dn, parent);
771 if (ret != LDB_SUCCESS) {
775 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
777 return LDB_ERR_OPERATIONS_ERROR;
780 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
786 find a 'reference' DN that points at another object
787 (eg. serverReference, rIDManagerReference etc)
789 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
790 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
792 const char *attrs[2];
793 struct ldb_result *res;
796 attrs[0] = attribute;
799 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
800 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
801 if (ret != LDB_SUCCESS) {
805 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
806 mem_ctx, res->msgs[0], attribute);
808 ldb_reset_err_string(ldb_module_get_ctx(module));
810 return LDB_ERR_NO_SUCH_ATTRIBUTE;
818 find the RID Manager$ DN via the rIDManagerReference attribute in the
821 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
822 struct ldb_request *parent)
824 return dsdb_module_reference_dn(module, mem_ctx,
825 ldb_get_default_basedn(ldb_module_get_ctx(module)),
826 "rIDManagerReference", dn, parent);
830 used to chain to the callers callback
832 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
834 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
836 talloc_steal(up_req, req);
837 return up_req->callback(up_req, ares);
841 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
842 object for a partition
844 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
845 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
847 struct ldb_context *ldb = ldb_module_get_ctx(module);
848 struct ldb_request *req;
850 TALLOC_CTX *tmp_ctx = talloc_new(module);
851 struct dsdb_control_current_partition *p_ctrl;
852 struct ldb_result *res;
854 res = talloc_zero(tmp_ctx, struct ldb_result);
856 talloc_free(tmp_ctx);
857 return ldb_module_oom(module);
860 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
861 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
865 res, ldb_search_default_callback,
867 LDB_REQ_SET_LOCATION(req);
868 if (ret != LDB_SUCCESS) {
869 talloc_free(tmp_ctx);
873 p_ctrl = talloc(req, struct dsdb_control_current_partition);
874 if (p_ctrl == NULL) {
875 talloc_free(tmp_ctx);
876 return ldb_module_oom(module);
878 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
882 ret = ldb_request_add_control(req,
883 DSDB_CONTROL_CURRENT_PARTITION_OID,
885 if (ret != LDB_SUCCESS) {
886 talloc_free(tmp_ctx);
890 /* Run the new request */
891 ret = ldb_next_request(module, req);
893 if (ret == LDB_SUCCESS) {
894 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
897 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
898 /* it hasn't been created yet, which means
899 an implicit value of zero */
901 talloc_free(tmp_ctx);
902 ldb_reset_err_string(ldb);
906 if (ret != LDB_SUCCESS) {
907 talloc_free(tmp_ctx);
911 if (res->count != 1) {
917 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
919 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
923 talloc_free(tmp_ctx);
929 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
932 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
933 uint64_t uSN, uint64_t urgent_uSN,
934 struct ldb_request *parent)
936 struct ldb_context *ldb = ldb_module_get_ctx(module);
937 struct ldb_request *req;
938 struct ldb_message *msg;
939 struct dsdb_control_current_partition *p_ctrl;
941 struct ldb_result *res;
943 msg = ldb_msg_new(module);
945 return ldb_module_oom(module);
948 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
949 if (msg->dn == NULL) {
951 return ldb_operr(ldb_module_get_ctx(module));
954 res = talloc_zero(msg, struct ldb_result);
957 return ldb_module_oom(module);
960 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
961 if (ret != LDB_SUCCESS) {
965 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
967 /* urgent_uSN is optional so may not be stored */
969 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
971 if (ret != LDB_SUCCESS) {
975 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
979 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
980 if (p_ctrl == NULL) {
984 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
986 ret = ldb_build_mod_req(&req, ldb, msg,
990 ldb_modify_default_callback,
992 LDB_REQ_SET_LOCATION(req);
994 if (ret != LDB_SUCCESS) {
999 ret = ldb_request_add_control(req,
1000 DSDB_CONTROL_CURRENT_PARTITION_OID,
1002 if (ret != LDB_SUCCESS) {
1007 /* Run the new request */
1008 ret = ldb_next_request(module, req);
1010 if (ret == LDB_SUCCESS) {
1011 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1013 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1014 ret = ldb_build_add_req(&req, ldb, msg,
1018 ldb_modify_default_callback,
1020 LDB_REQ_SET_LOCATION(req);
1029 bool dsdb_module_am_system(struct ldb_module *module)
1031 struct ldb_context *ldb = ldb_module_get_ctx(module);
1032 struct auth_session_info *session_info
1033 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1034 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1037 bool dsdb_module_am_administrator(struct ldb_module *module)
1039 struct ldb_context *ldb = ldb_module_get_ctx(module);
1040 struct auth_session_info *session_info
1041 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1042 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1046 check if the recyclebin is enabled
1048 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1050 struct ldb_context *ldb = ldb_module_get_ctx(module);
1051 struct GUID recyclebin_guid;
1054 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1056 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1057 if (ret != LDB_SUCCESS) {
1058 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1059 return LDB_ERR_UNWILLING_TO_PERFORM;
1065 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1066 struct ldb_message *msg,
1068 const int32_t *old_val,
1069 const int32_t *new_val)
1071 struct ldb_message_element *el;
1076 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1077 if (ret != LDB_SUCCESS) {
1081 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1083 return ldb_module_oom(module);
1085 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1087 return ldb_module_oom(module);
1089 *el->values = data_blob_string_const(vstring);
1093 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1094 if (ret != LDB_SUCCESS) {
1098 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1100 return ldb_module_oom(module);
1102 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1104 return ldb_module_oom(module);
1106 *el->values = data_blob_string_const(vstring);
1112 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1113 struct ldb_message *msg,
1115 const uint32_t *old_val,
1116 const uint32_t *new_val)
1118 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1119 (const int32_t *)old_val,
1120 (const int32_t *)new_val);
1123 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1124 struct ldb_message *msg,
1126 const int64_t *old_val,
1127 const int64_t *new_val)
1129 struct ldb_message_element *el;
1134 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1135 if (ret != LDB_SUCCESS) {
1139 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1141 return ldb_module_oom(module);
1143 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1145 return ldb_module_oom(module);
1147 *el->values = data_blob_string_const(vstring);
1151 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1152 if (ret != LDB_SUCCESS) {
1156 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1158 return ldb_module_oom(module);
1160 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1162 return ldb_module_oom(module);
1164 *el->values = data_blob_string_const(vstring);
1170 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1171 struct ldb_message *msg,
1173 const uint64_t *old_val,
1174 const uint64_t *new_val)
1176 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1177 (const int64_t *)old_val,
1178 (const int64_t *)new_val);
1182 update an int32 attribute safely via a constrained delete/add
1184 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1187 const int32_t *old_val,
1188 const int32_t *new_val,
1189 struct ldb_request *parent)
1191 struct ldb_message *msg;
1194 msg = ldb_msg_new(module);
1196 return ldb_module_oom(module);
1200 ret = dsdb_msg_constrainted_update_int32(module,
1204 if (ret != LDB_SUCCESS) {
1209 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1214 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1217 const uint32_t *old_val,
1218 const uint32_t *new_val,
1219 struct ldb_request *parent)
1221 return dsdb_module_constrainted_update_int32(module, dn, attr,
1222 (const int32_t *)old_val,
1223 (const int32_t *)new_val, parent);
1227 update an int64 attribute safely via a constrained delete/add
1229 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1232 const int64_t *old_val,
1233 const int64_t *new_val,
1234 struct ldb_request *parent)
1236 struct ldb_message *msg;
1239 msg = ldb_msg_new(module);
1241 return ldb_module_oom(module);
1245 ret = dsdb_msg_constrainted_update_int64(module,
1249 if (ret != LDB_SUCCESS) {
1254 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1259 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1262 const uint64_t *old_val,
1263 const uint64_t *new_val,
1264 struct ldb_request *parent)
1266 return dsdb_module_constrainted_update_int64(module, dn, attr,
1267 (const int64_t *)old_val,
1268 (const int64_t *)new_val,
1273 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1274 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1277 struct ldb_dn *new_dn;
1278 struct ldb_context *ldb = ldb_module_get_ctx(module);
1279 static const char *attrs[] = { "dSHeuristics", NULL };
1280 struct ldb_result *res;
1282 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1283 if (!ldb_dn_add_child_fmt(new_dn,
1284 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1285 talloc_free(new_dn);
1288 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1291 DSDB_FLAG_NEXT_MODULE,
1293 if (ret == LDB_SUCCESS && res->count == 1) {
1294 talloc_free(new_dn);
1295 return ldb_msg_find_ldb_val(res->msgs[0],
1298 talloc_free(new_dn);
1302 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1304 TALLOC_CTX *tmp_ctx = talloc_new(module);
1306 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1308 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1310 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1316 talloc_free(tmp_ctx);
1320 bool dsdb_user_password_support(struct ldb_module *module,
1321 TALLOC_CTX *mem_ctx,
1322 struct ldb_request *parent)
1324 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1326 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1329 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1331 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1332 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1338 talloc_free(tmp_ctx);
1343 show the chain of requests, useful for debugging async requests
1345 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1347 char *s = ldb_module_call_chain(req, req);
1348 DEBUG(level, ("%s\n", s));
1353 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1354 * performing a modify operation.
1356 * In order that the constraint checking by the "objectclass_attrs" LDB module
1357 * does work properly, the change request should remain similar or only be
1358 * enhanced (no other modifications as deletions, variations).
1360 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1361 const char *attr_name,
1362 enum ldb_request_type operation)
1364 struct ldb_message_element *el = NULL;
1367 /* We've to walk over all modification entries and consider the last
1368 * non-delete one which belongs to "attr_name".
1370 * If "el" is NULL afterwards then that means there was no interesting
1372 for (i = 0; i < msg->num_elements; i++) {
1373 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1374 if ((operation == LDB_MODIFY) &&
1375 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1376 == LDB_FLAG_MOD_DELETE)) {
1379 el = &msg->elements[i];
1387 * This function determines the (last) structural or 88 object class of a passed
1388 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1389 * Without schema this does not work and hence NULL is returned.
1391 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1392 const struct ldb_message_element *element)
1394 const struct dsdb_class *last_class;
1396 if (schema == NULL) {
1400 if (element->num_values == 0) {
1404 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1405 &element->values[element->num_values-1]);
1406 if (last_class == NULL) {
1409 if (last_class->objectClassCategory > 1) {
1416 const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1417 const struct ldb_message *msg)
1419 struct ldb_message_element *oc_el;
1421 oc_el = ldb_msg_find_element(msg, "objectClass");
1426 return dsdb_get_last_structural_class(schema, oc_el);
1429 /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1430 cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
1431 CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
1433 int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1436 char *upper_rdn_attr;
1438 for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1439 /* We need the attribute name in upper case */
1440 upper_rdn_attr = strupper_talloc(dn,
1441 ldb_dn_get_component_name(dn, i));
1442 if (!upper_rdn_attr) {
1443 return ldb_oom(ldb);
1445 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1446 *ldb_dn_get_component_val(dn, i));
1447 talloc_free(upper_rdn_attr);
1448 if (ret != LDB_SUCCESS) {
1456 * Make most specific objectCategory for the objectClass of passed object
1457 * NOTE: In this implementation we count that it is called on already
1458 * verified objectClass attribute value. See objectclass.c thorough
1459 * implementation for all the magic that involves
1461 * @param ldb ldb context
1462 * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1463 * Hence leave the responsibility to the caller.
1464 * @param obj AD object to determint objectCategory for
1465 * @param mem_ctx Memory context - usually it is obj actually
1466 * @param pobjectcategory location to store found objectCategory
1468 * @return LDB_SUCCESS or error including out of memory error
1470 int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1471 struct ldb_message *obj,
1472 TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1474 const struct dsdb_class *objectclass;
1475 struct ldb_message_element *objectclass_element;
1476 struct dsdb_extended_dn_store_format *dn_format;
1478 objectclass_element = ldb_msg_find_element(obj, "objectClass");
1479 if (!objectclass_element) {
1480 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1481 ldb_dn_get_linearized(obj->dn));
1482 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1484 if (objectclass_element->num_values == 0) {
1485 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1486 ldb_dn_get_linearized(obj->dn));
1487 return LDB_ERR_CONSTRAINT_VIOLATION;
1491 * Get the new top-most structural object class and check for
1492 * unrelated structural classes
1494 objectclass = dsdb_get_last_structural_class(schema,
1495 objectclass_element);
1496 if (objectclass == NULL) {
1497 ldb_asprintf_errstring(ldb,
1498 "Failed to find a structural class for %s",
1499 ldb_dn_get_linearized(obj->dn));
1500 return LDB_ERR_UNWILLING_TO_PERFORM;
1503 dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1504 struct dsdb_extended_dn_store_format);
1505 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1506 /* Strip off extended components */
1507 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1508 objectclass->defaultObjectCategory);
1509 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1512 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1515 if (*pobjectcategory == NULL) {
1516 return ldb_oom(ldb);