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"
35 search for attrs on one DN, in the modules below
37 int dsdb_module_search_dn(struct ldb_module *module,
39 struct ldb_result **_res,
40 struct ldb_dn *basedn,
41 const char * const *attrs,
43 struct ldb_request *parent)
46 struct ldb_request *req;
48 struct ldb_result *res;
50 tmp_ctx = talloc_new(mem_ctx);
51 if (tmp_ctx == NULL) {
52 return ldb_oom(ldb_module_get_ctx(module));
55 res = talloc_zero(tmp_ctx, struct ldb_result);
58 return ldb_oom(ldb_module_get_ctx(module));
61 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
68 ldb_search_default_callback,
70 LDB_REQ_SET_LOCATION(req);
71 if (ret != LDB_SUCCESS) {
76 ret = dsdb_request_add_controls(req, dsdb_flags);
77 if (ret != LDB_SUCCESS) {
82 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
83 ldb_req_mark_trusted(req);
86 /* Run the new request */
87 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
88 ret = ldb_next_request(module, req);
89 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
90 ret = ldb_request(ldb_module_get_ctx(module), req);
92 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
93 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
94 ret = ops->search(module, req);
96 if (ret == LDB_SUCCESS) {
97 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
100 if (ret != LDB_SUCCESS) {
101 talloc_free(tmp_ctx);
105 if (res->count != 1) {
106 /* we may be reading a DB that does not have the 'check base on search' option... */
107 ret = LDB_ERR_NO_SUCH_OBJECT;
108 ldb_asprintf_errstring(ldb_module_get_ctx(module),
109 "dsdb_module_search_dn: did not find base dn %s (%d results)",
110 ldb_dn_get_linearized(basedn), res->count);
112 *_res = talloc_steal(mem_ctx, res);
114 talloc_free(tmp_ctx);
118 int dsdb_module_search_tree(struct ldb_module *module,
120 struct ldb_result **_res,
121 struct ldb_dn *basedn,
122 enum ldb_scope scope,
123 struct ldb_parse_tree *tree,
124 const char * const *attrs,
126 struct ldb_request *parent)
129 struct ldb_request *req;
131 struct ldb_result *res;
133 tmp_ctx = talloc_new(mem_ctx);
134 if (tmp_ctx == NULL) {
135 return ldb_oom(ldb_module_get_ctx(module));
138 /* cross-partitions searches with a basedn break multi-domain support */
139 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
141 res = talloc_zero(tmp_ctx, struct ldb_result);
143 talloc_free(tmp_ctx);
144 return ldb_oom(ldb_module_get_ctx(module));
147 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
154 ldb_search_default_callback,
156 LDB_REQ_SET_LOCATION(req);
157 if (ret != LDB_SUCCESS) {
158 talloc_free(tmp_ctx);
162 ret = dsdb_request_add_controls(req, dsdb_flags);
163 if (ret != LDB_SUCCESS) {
164 talloc_free(tmp_ctx);
168 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
169 ldb_req_mark_trusted(req);
172 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
173 ret = ldb_next_request(module, req);
174 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
175 ret = ldb_request(ldb_module_get_ctx(module), req);
177 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
178 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
179 ret = ops->search(module, req);
181 if (ret == LDB_SUCCESS) {
182 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
185 if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
186 if (res->count == 0) {
187 talloc_free(tmp_ctx);
188 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
190 if (res->count != 1) {
191 talloc_free(tmp_ctx);
192 ldb_reset_err_string(ldb_module_get_ctx(module));
193 return LDB_ERR_CONSTRAINT_VIOLATION;
198 if (ret == LDB_SUCCESS) {
199 *_res = talloc_steal(mem_ctx, res);
201 talloc_free(tmp_ctx);
206 search for attrs in the modules below
208 int dsdb_module_search(struct ldb_module *module,
210 struct ldb_result **_res,
211 struct ldb_dn *basedn, enum ldb_scope scope,
212 const char * const *attrs,
214 struct ldb_request *parent,
215 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
221 struct ldb_parse_tree *tree;
223 /* cross-partitions searches with a basedn break multi-domain support */
224 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
226 tmp_ctx = talloc_new(mem_ctx);
227 if (tmp_ctx == NULL) {
228 return ldb_oom(ldb_module_get_ctx(module));
232 va_start(ap, format);
233 expression = talloc_vasprintf(tmp_ctx, format, ap);
237 talloc_free(tmp_ctx);
238 return ldb_oom(ldb_module_get_ctx(module));
244 tree = ldb_parse_tree(tmp_ctx, expression);
246 talloc_free(tmp_ctx);
247 ldb_set_errstring(ldb_module_get_ctx(module),
248 "Unable to parse search expression");
249 return LDB_ERR_OPERATIONS_ERROR;
252 ret = dsdb_module_search_tree(module,
262 talloc_free(tmp_ctx);
267 find an object given a GUID. This searches across all partitions
269 int dsdb_module_obj_by_guid(struct ldb_module *module,
271 struct ldb_message **_msg,
272 const struct GUID *guid,
273 const char * const *attrs,
274 struct ldb_request *parent)
276 struct ldb_result *res;
277 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
280 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
282 DSDB_FLAG_NEXT_MODULE |
283 DSDB_SEARCH_SHOW_RECYCLED |
284 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
285 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
287 "objectGUID=%s", GUID_string(tmp_ctx, guid));
288 if (ret != LDB_SUCCESS) {
289 talloc_free(tmp_ctx);
292 if (res->count == 0) {
293 talloc_free(tmp_ctx);
294 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
296 if (res->count != 1) {
297 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
298 GUID_string(tmp_ctx, guid));
299 talloc_free(tmp_ctx);
300 return LDB_ERR_OPERATIONS_ERROR;
303 *_msg = talloc_steal(mem_ctx, res->msgs[0]);
305 talloc_free(tmp_ctx);
310 find a DN given a GUID. This searches across all partitions
312 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
313 const struct GUID *guid, struct ldb_dn **dn,
314 struct ldb_request *parent)
316 struct ldb_message *msg = NULL;
317 static const char * const attrs[] = { NULL };
318 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
321 ret = dsdb_module_obj_by_guid(module,
327 if (ret != LDB_SUCCESS) {
328 talloc_free(tmp_ctx);
332 *dn = talloc_steal(mem_ctx, msg->dn);
334 talloc_free(tmp_ctx);
339 find a GUID given a DN.
341 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
342 struct ldb_request *parent)
344 static const char * const attrs[] = { NULL };
345 struct ldb_result *res;
346 TALLOC_CTX *tmp_ctx = talloc_new(module);
350 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
351 DSDB_FLAG_NEXT_MODULE |
352 DSDB_SEARCH_SHOW_RECYCLED |
353 DSDB_SEARCH_SHOW_EXTENDED_DN,
355 if (ret != LDB_SUCCESS) {
356 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
357 ldb_dn_get_linearized(dn));
358 talloc_free(tmp_ctx);
362 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
363 if (!NT_STATUS_IS_OK(status)) {
364 talloc_free(tmp_ctx);
365 return ldb_operr(ldb_module_get_ctx(module));
368 talloc_free(tmp_ctx);
374 a ldb_extended request operating on modules below the
377 Note that this does not automatically start a transaction. If you
378 need a transaction the caller needs to start it as needed.
380 int dsdb_module_extended(struct ldb_module *module,
382 struct ldb_result **_res,
383 const char* oid, void* data,
385 struct ldb_request *parent)
387 struct ldb_request *req;
389 struct ldb_context *ldb = ldb_module_get_ctx(module);
390 TALLOC_CTX *tmp_ctx = talloc_new(module);
391 struct ldb_result *res;
397 res = talloc_zero(tmp_ctx, struct ldb_result);
399 talloc_free(tmp_ctx);
400 return ldb_oom(ldb_module_get_ctx(module));
403 ret = ldb_build_extended_req(&req, ldb,
408 res, ldb_extended_default_callback,
411 LDB_REQ_SET_LOCATION(req);
412 if (ret != LDB_SUCCESS) {
413 talloc_free(tmp_ctx);
417 ret = dsdb_request_add_controls(req, dsdb_flags);
418 if (ret != LDB_SUCCESS) {
419 talloc_free(tmp_ctx);
423 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
424 ldb_req_mark_trusted(req);
427 /* Run the new request */
428 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
429 ret = ldb_next_request(module, req);
430 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
431 ret = ldb_request(ldb_module_get_ctx(module), req);
433 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
434 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
435 ret = ops->extended(module, req);
437 if (ret == LDB_SUCCESS) {
438 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
441 if (_res != NULL && ret == LDB_SUCCESS) {
442 (*_res) = talloc_steal(mem_ctx, res);
445 talloc_free(tmp_ctx);
451 a ldb_modify request operating on modules below the
454 int dsdb_module_modify(struct ldb_module *module,
455 const struct ldb_message *message,
457 struct ldb_request *parent)
459 struct ldb_request *mod_req;
461 struct ldb_context *ldb = ldb_module_get_ctx(module);
462 TALLOC_CTX *tmp_ctx = talloc_new(module);
463 struct ldb_result *res;
465 res = talloc_zero(tmp_ctx, struct ldb_result);
467 talloc_free(tmp_ctx);
468 return ldb_oom(ldb_module_get_ctx(module));
471 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
475 ldb_modify_default_callback,
477 LDB_REQ_SET_LOCATION(mod_req);
478 if (ret != LDB_SUCCESS) {
479 talloc_free(tmp_ctx);
483 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
484 if (ret != LDB_SUCCESS) {
485 talloc_free(tmp_ctx);
489 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
490 ldb_req_mark_trusted(mod_req);
493 /* Run the new request */
494 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
495 ret = ldb_next_request(module, mod_req);
496 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
497 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
499 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
500 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
501 ret = ops->modify(module, mod_req);
503 if (ret == LDB_SUCCESS) {
504 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
507 talloc_free(tmp_ctx);
514 a ldb_rename request operating on modules below the
517 int dsdb_module_rename(struct ldb_module *module,
518 struct ldb_dn *olddn, struct ldb_dn *newdn,
520 struct ldb_request *parent)
522 struct ldb_request *req;
524 struct ldb_context *ldb = ldb_module_get_ctx(module);
525 TALLOC_CTX *tmp_ctx = talloc_new(module);
526 struct ldb_result *res;
528 res = talloc_zero(tmp_ctx, struct ldb_result);
530 talloc_free(tmp_ctx);
531 return ldb_oom(ldb_module_get_ctx(module));
534 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
539 ldb_modify_default_callback,
541 LDB_REQ_SET_LOCATION(req);
542 if (ret != LDB_SUCCESS) {
543 talloc_free(tmp_ctx);
547 ret = dsdb_request_add_controls(req, dsdb_flags);
548 if (ret != LDB_SUCCESS) {
549 talloc_free(tmp_ctx);
553 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
554 ldb_req_mark_trusted(req);
557 /* Run the new request */
558 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
559 ret = ldb_next_request(module, req);
560 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
561 ret = ldb_request(ldb_module_get_ctx(module), req);
563 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
564 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
565 ret = ops->rename(module, req);
567 if (ret == LDB_SUCCESS) {
568 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
571 talloc_free(tmp_ctx);
576 a ldb_add request operating on modules below the
579 int dsdb_module_add(struct ldb_module *module,
580 const struct ldb_message *message,
582 struct ldb_request *parent)
584 struct ldb_request *req;
586 struct ldb_context *ldb = ldb_module_get_ctx(module);
587 TALLOC_CTX *tmp_ctx = talloc_new(module);
588 struct ldb_result *res;
590 res = talloc_zero(tmp_ctx, struct ldb_result);
592 talloc_free(tmp_ctx);
593 return ldb_oom(ldb_module_get_ctx(module));
596 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
600 ldb_modify_default_callback,
602 LDB_REQ_SET_LOCATION(req);
603 if (ret != LDB_SUCCESS) {
604 talloc_free(tmp_ctx);
608 ret = dsdb_request_add_controls(req, dsdb_flags);
609 if (ret != LDB_SUCCESS) {
610 talloc_free(tmp_ctx);
614 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
615 ldb_req_mark_trusted(req);
618 /* Run the new request */
619 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
620 ret = ldb_next_request(module, req);
621 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
622 ret = ldb_request(ldb_module_get_ctx(module), req);
624 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
625 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
626 ret = ops->add(module, req);
628 if (ret == LDB_SUCCESS) {
629 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
632 talloc_free(tmp_ctx);
637 a ldb_delete request operating on modules below the
640 int dsdb_module_del(struct ldb_module *module,
643 struct ldb_request *parent)
645 struct ldb_request *req;
647 struct ldb_context *ldb = ldb_module_get_ctx(module);
648 TALLOC_CTX *tmp_ctx = talloc_new(module);
649 struct ldb_result *res;
651 res = talloc_zero(tmp_ctx, struct ldb_result);
653 talloc_free(tmp_ctx);
657 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
661 ldb_modify_default_callback,
663 LDB_REQ_SET_LOCATION(req);
664 if (ret != LDB_SUCCESS) {
665 talloc_free(tmp_ctx);
669 ret = dsdb_request_add_controls(req, dsdb_flags);
670 if (ret != LDB_SUCCESS) {
671 talloc_free(tmp_ctx);
675 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
676 ldb_req_mark_trusted(req);
679 /* Run the new request */
680 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
681 ret = ldb_next_request(module, req);
682 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
683 ret = ldb_request(ldb_module_get_ctx(module), req);
685 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
686 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
687 ret = ops->del(module, req);
689 if (ret == LDB_SUCCESS) {
690 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
693 talloc_free(tmp_ctx);
698 check if a single valued link has multiple non-deleted values
700 This is needed when we will be using the RELAX control to stop
701 ldb_tdb from checking single valued links
703 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
704 const struct ldb_message_element *el)
706 bool found_active = false;
709 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
710 el->num_values < 2) {
714 for (i=0; i<el->num_values; i++) {
715 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
717 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
727 int dsdb_check_samba_compatible_feature(struct ldb_module *module,
731 struct ldb_context *ldb = ldb_module_get_ctx(module);
732 struct ldb_result *res;
733 static const char * const samba_dsdb_attrs[] = {
734 SAMBA_COMPATIBLE_FEATURES_ATTR,
738 struct ldb_dn *samba_dsdb_dn = NULL;
739 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
740 if (tmp_ctx == NULL) {
746 samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
747 if (samba_dsdb_dn == NULL) {
748 TALLOC_FREE(tmp_ctx);
752 ret = dsdb_module_search_dn(module,
757 DSDB_FLAG_NEXT_MODULE,
759 if (ret == LDB_SUCCESS) {
760 *found = ldb_msg_check_string_attribute(
762 SAMBA_COMPATIBLE_FEATURES_ATTR,
764 } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
765 /* it is not an error not to find it */
768 TALLOC_FREE(tmp_ctx);
774 check if an optional feature is enabled on our own NTDS DN
776 Note that features can be marked as enabled in more than one
777 place. For example, the recyclebin feature is marked as enabled both
778 on the CN=Partitions,CN=Configuration object and on the NTDS DN of
779 each DC in the forest. It seems likely that it is the job of the KCC
780 to propagate between the two
782 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
785 struct ldb_context *ldb = ldb_module_get_ctx(module);
786 struct ldb_result *res;
787 struct ldb_dn *search_dn;
788 struct GUID search_guid;
789 static const char * const attrs[] = {"msDS-EnabledFeature", NULL};
792 struct ldb_message_element *el;
793 struct ldb_dn *feature_dn;
795 tmp_ctx = talloc_new(ldb);
797 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
798 if (feature_dn == NULL) {
799 talloc_free(tmp_ctx);
800 return ldb_operr(ldb_module_get_ctx(module));
803 *feature_enabled = false;
805 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
806 if (ret != LDB_SUCCESS) {
807 ldb_asprintf_errstring(ldb,
808 "Could not find the feature object - dn: %s\n",
809 ldb_dn_get_linearized(feature_dn));
810 talloc_free(tmp_ctx);
811 return LDB_ERR_NO_SUCH_OBJECT;
813 if (res->msgs[0]->num_elements > 0) {
814 static const char * const attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
816 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
818 for (i=0; i<el->num_values; i++) {
819 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
821 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
822 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
823 if (ret != LDB_SUCCESS) {
824 ldb_asprintf_errstring(ldb,
825 "Could no find object dn: %s\n",
826 ldb_dn_get_linearized(search_dn));
827 talloc_free(tmp_ctx);
828 return LDB_ERR_OPERATIONS_ERROR;
831 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
833 if (GUID_equal(&search_guid, &op_feature_guid)) {
834 *feature_enabled = true;
839 talloc_free(tmp_ctx);
844 find the NTDS GUID from a computers DN record
846 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
848 struct ldb_dn *computer_dn,
849 struct GUID *ntds_guid,
850 struct ldb_request *parent)
855 *ntds_guid = GUID_zero();
857 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
858 "serverReferenceBL", &dn, parent);
859 if (ret != LDB_SUCCESS) {
863 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
865 return LDB_ERR_OPERATIONS_ERROR;
868 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
874 find a 'reference' DN that points at another object
875 (eg. serverReference, rIDManagerReference etc)
877 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
878 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
880 const char *attrs[2];
881 struct ldb_result *res;
884 attrs[0] = attribute;
887 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
888 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
889 if (ret != LDB_SUCCESS) {
893 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
894 mem_ctx, res->msgs[0], attribute);
896 ldb_reset_err_string(ldb_module_get_ctx(module));
898 return LDB_ERR_NO_SUCH_ATTRIBUTE;
906 find the RID Manager$ DN via the rIDManagerReference attribute in the
909 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
910 struct ldb_request *parent)
912 return dsdb_module_reference_dn(module, mem_ctx,
913 ldb_get_default_basedn(ldb_module_get_ctx(module)),
914 "rIDManagerReference", dn, parent);
918 used to chain to the callers callback
920 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
922 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
925 return ldb_module_done(up_req, NULL, NULL,
926 LDB_ERR_OPERATIONS_ERROR);
929 if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
930 return ldb_module_done(up_req, ares->controls,
931 ares->response, ares->error);
934 /* Otherwise pass on the callback */
935 switch (ares->type) {
936 case LDB_REPLY_ENTRY:
937 return ldb_module_send_entry(up_req, ares->message,
940 case LDB_REPLY_REFERRAL:
941 return ldb_module_send_referral(up_req,
945 return LDB_ERR_OPERATIONS_ERROR;
950 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
951 object for a partition
953 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
954 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
956 struct ldb_context *ldb = ldb_module_get_ctx(module);
957 struct ldb_request *req;
959 TALLOC_CTX *tmp_ctx = talloc_new(module);
960 struct dsdb_control_current_partition *p_ctrl;
961 struct ldb_result *res;
963 res = talloc_zero(tmp_ctx, struct ldb_result);
965 talloc_free(tmp_ctx);
966 return ldb_module_oom(module);
969 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
970 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
974 res, ldb_search_default_callback,
976 LDB_REQ_SET_LOCATION(req);
977 if (ret != LDB_SUCCESS) {
978 talloc_free(tmp_ctx);
982 p_ctrl = talloc(req, struct dsdb_control_current_partition);
983 if (p_ctrl == NULL) {
984 talloc_free(tmp_ctx);
985 return ldb_module_oom(module);
987 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
991 ret = ldb_request_add_control(req,
992 DSDB_CONTROL_CURRENT_PARTITION_OID,
994 if (ret != LDB_SUCCESS) {
995 talloc_free(tmp_ctx);
999 /* Run the new request */
1000 ret = ldb_next_request(module, req);
1002 if (ret == LDB_SUCCESS) {
1003 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1006 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
1007 /* it hasn't been created yet, which means
1008 an implicit value of zero */
1010 talloc_free(tmp_ctx);
1011 ldb_reset_err_string(ldb);
1015 if (ret != LDB_SUCCESS) {
1016 talloc_free(tmp_ctx);
1020 if (res->count != 1) {
1026 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
1028 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
1032 talloc_free(tmp_ctx);
1038 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
1041 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
1042 uint64_t uSN, uint64_t urgent_uSN,
1043 struct ldb_request *parent)
1045 struct ldb_context *ldb = ldb_module_get_ctx(module);
1046 struct ldb_request *req;
1047 struct ldb_message *msg;
1048 struct dsdb_control_current_partition *p_ctrl;
1050 struct ldb_result *res;
1052 msg = ldb_msg_new(module);
1054 return ldb_module_oom(module);
1057 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
1058 if (msg->dn == NULL) {
1060 return ldb_operr(ldb_module_get_ctx(module));
1063 res = talloc_zero(msg, struct ldb_result);
1066 return ldb_module_oom(module);
1069 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
1070 if (ret != LDB_SUCCESS) {
1074 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1076 /* urgent_uSN is optional so may not be stored */
1078 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
1080 if (ret != LDB_SUCCESS) {
1084 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1088 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1089 if (p_ctrl == NULL) {
1091 return ldb_oom(ldb);
1093 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1095 ret = ldb_build_mod_req(&req, ldb, msg,
1099 ldb_modify_default_callback,
1101 LDB_REQ_SET_LOCATION(req);
1103 if (ret != LDB_SUCCESS) {
1108 ret = ldb_request_add_control(req,
1109 DSDB_CONTROL_CURRENT_PARTITION_OID,
1111 if (ret != LDB_SUCCESS) {
1116 /* Run the new request */
1117 ret = ldb_next_request(module, req);
1119 if (ret == LDB_SUCCESS) {
1120 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1122 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1123 ret = ldb_build_add_req(&req, ldb, msg,
1127 ldb_modify_default_callback,
1129 LDB_REQ_SET_LOCATION(req);
1138 bool dsdb_module_am_system(struct ldb_module *module)
1140 struct ldb_context *ldb = ldb_module_get_ctx(module);
1141 struct auth_session_info *session_info
1143 ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1144 struct auth_session_info);
1145 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1148 bool dsdb_module_am_administrator(struct ldb_module *module)
1150 struct ldb_context *ldb = ldb_module_get_ctx(module);
1151 struct auth_session_info *session_info
1153 ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1154 struct auth_session_info);
1155 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1159 * Return ‘true’ if the caller has system access. The ‘acl’ module passes
1160 * SYSTEM_CONTROL_STRIP_CRITICAL when it wants to strip the critical flag.
1162 bool dsdb_have_system_access(
1163 struct ldb_module *module,
1164 struct ldb_request *req,
1165 const enum system_control_strip_critical strip_critical)
1167 struct ldb_control *as_system = NULL;
1169 as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
1170 if (as_system != NULL) {
1171 switch (strip_critical) {
1172 case SYSTEM_CONTROL_KEEP_CRITICAL:
1174 case SYSTEM_CONTROL_STRIP_CRITICAL:
1175 as_system->critical = 0;
1182 return dsdb_module_am_system(module);
1186 check if the recyclebin is enabled
1188 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1190 struct ldb_context *ldb = ldb_module_get_ctx(module);
1191 struct GUID recyclebin_guid;
1194 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1196 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1197 if (ret != LDB_SUCCESS) {
1198 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1205 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1206 struct ldb_message *msg,
1208 const int32_t *old_val,
1209 const int32_t *new_val)
1211 struct ldb_message_element *el;
1216 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1217 if (ret != LDB_SUCCESS) {
1221 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1223 return ldb_module_oom(module);
1225 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1227 return ldb_module_oom(module);
1229 *el->values = data_blob_string_const(vstring);
1233 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1234 if (ret != LDB_SUCCESS) {
1238 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1240 return ldb_module_oom(module);
1242 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1244 return ldb_module_oom(module);
1246 *el->values = data_blob_string_const(vstring);
1252 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1253 struct ldb_message *msg,
1255 const uint32_t *old_val,
1256 const uint32_t *new_val)
1258 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1259 (const int32_t *)old_val,
1260 (const int32_t *)new_val);
1263 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1264 struct ldb_message *msg,
1266 const int64_t *old_val,
1267 const int64_t *new_val)
1269 struct ldb_message_element *el;
1274 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1275 if (ret != LDB_SUCCESS) {
1279 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1281 return ldb_module_oom(module);
1283 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1285 return ldb_module_oom(module);
1287 *el->values = data_blob_string_const(vstring);
1291 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1292 if (ret != LDB_SUCCESS) {
1296 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1298 return ldb_module_oom(module);
1300 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1302 return ldb_module_oom(module);
1304 *el->values = data_blob_string_const(vstring);
1310 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1311 struct ldb_message *msg,
1313 const uint64_t *old_val,
1314 const uint64_t *new_val)
1316 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1317 (const int64_t *)old_val,
1318 (const int64_t *)new_val);
1322 update an int32 attribute safely via a constrained delete/add
1324 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1327 const int32_t *old_val,
1328 const int32_t *new_val,
1329 struct ldb_request *parent)
1331 struct ldb_message *msg;
1334 msg = ldb_msg_new(module);
1336 return ldb_module_oom(module);
1340 ret = dsdb_msg_constrainted_update_int32(module,
1344 if (ret != LDB_SUCCESS) {
1349 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1354 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1357 const uint32_t *old_val,
1358 const uint32_t *new_val,
1359 struct ldb_request *parent)
1361 return dsdb_module_constrainted_update_int32(module, dn, attr,
1362 (const int32_t *)old_val,
1363 (const int32_t *)new_val, parent);
1367 update an int64 attribute safely via a constrained delete/add
1369 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1372 const int64_t *old_val,
1373 const int64_t *new_val,
1374 struct ldb_request *parent)
1376 struct ldb_message *msg;
1379 msg = ldb_msg_new(module);
1381 return ldb_module_oom(module);
1385 ret = dsdb_msg_constrainted_update_int64(module,
1389 if (ret != LDB_SUCCESS) {
1394 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1399 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1402 const uint64_t *old_val,
1403 const uint64_t *new_val,
1404 struct ldb_request *parent)
1406 return dsdb_module_constrainted_update_int64(module, dn, attr,
1407 (const int64_t *)old_val,
1408 (const int64_t *)new_val,
1413 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1414 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1417 struct ldb_dn *new_dn;
1418 struct ldb_context *ldb = ldb_module_get_ctx(module);
1419 static const char * const attrs[] = { "dSHeuristics", NULL };
1420 struct ldb_result *res;
1422 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1423 if (!ldb_dn_add_child_fmt(new_dn,
1424 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1425 talloc_free(new_dn);
1428 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1431 DSDB_FLAG_NEXT_MODULE,
1433 if (ret == LDB_SUCCESS && res->count == 1) {
1434 talloc_free(new_dn);
1435 return ldb_msg_find_ldb_val(res->msgs[0],
1438 talloc_free(new_dn);
1442 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1444 TALLOC_CTX *tmp_ctx = talloc_new(module);
1446 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1448 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1450 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1456 talloc_free(tmp_ctx);
1460 bool dsdb_user_password_support(struct ldb_module *module,
1461 TALLOC_CTX *mem_ctx,
1462 struct ldb_request *parent)
1464 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1466 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1469 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1471 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1472 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1478 talloc_free(tmp_ctx);
1482 bool dsdb_do_list_object(struct ldb_module *module,
1483 TALLOC_CTX *mem_ctx,
1484 struct ldb_request *parent)
1486 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1488 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1491 if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
1493 } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
1499 talloc_free(tmp_ctx);
1503 bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
1504 TALLOC_CTX *mem_ctx,
1505 struct ldb_request *parent)
1507 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1508 bool result = false;
1509 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1512 if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) {
1513 uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1];
1514 if (val != '0' && val != '2') {
1519 talloc_free(tmp_ctx);
1523 bool dsdb_block_owner_implicit_rights(struct ldb_module *module,
1524 TALLOC_CTX *mem_ctx,
1525 struct ldb_request *parent)
1527 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1528 bool result = false;
1529 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1532 if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) {
1533 uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1];
1534 if (val != '0' && val != '2') {
1539 talloc_free(tmp_ctx);
1544 show the chain of requests, useful for debugging async requests
1546 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1548 char *s = ldb_module_call_chain(req, req);
1549 DEBUG(level, ("%s\n", s));
1554 * Get all the values that *might* be added by an ldb message, as a composite
1557 * This is useful when we need to check all the possible values against some
1560 * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES,
1561 * the returned element might contain more values than would actually end up
1562 * in the database if the message was run to its conclusion.
1564 * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is
1567 * The returned element might not be new, and should not be modified or freed
1568 * before the message is finished.
1571 int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
1572 const struct ldb_message *msg,
1573 const char *attr_name,
1574 struct ldb_message_element **el,
1575 enum ldb_request_type operation)
1578 unsigned int el_count = 0;
1579 unsigned int val_count = 0;
1580 struct ldb_val *v = NULL;
1581 struct ldb_message_element *_el = NULL;
1584 if (operation != LDB_ADD && operation != LDB_MODIFY) {
1585 DBG_ERR("inapplicable operation type: %d\n", operation);
1586 return LDB_ERR_OPERATIONS_ERROR;
1589 /* count the adding or replacing elements */
1590 for (i = 0; i < msg->num_elements; i++) {
1591 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1593 if ((operation == LDB_MODIFY) &&
1594 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1595 == LDB_FLAG_MOD_DELETE)) {
1599 tmp = val_count + msg->elements[i].num_values;
1600 if (unlikely(tmp < val_count)) {
1601 DBG_ERR("too many values for one element!\n");
1602 return LDB_ERR_OPERATIONS_ERROR;
1607 if (el_count == 0) {
1608 /* nothing to see here */
1612 if (el_count == 1 || val_count == 0) {
1614 * There is one effective element, which we can return as-is,
1615 * OR there are only elements with zero values -- any of which
1618 for (i = 0; i < msg->num_elements; i++) {
1619 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1620 if ((operation == LDB_MODIFY) &&
1621 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1622 == LDB_FLAG_MOD_DELETE)) {
1625 *el = &msg->elements[i];
1631 _el = talloc_zero(mem_ctx, struct ldb_message_element);
1633 return LDB_ERR_OPERATIONS_ERROR;
1635 _el->name = attr_name;
1637 if (val_count == 0) {
1639 * Seems unlikely, but sometimes we might be adding zero
1640 * values in multiple separate elements. The talloc zero has
1641 * already set the expected values = NULL, num_values = 0.
1647 _el->values = talloc_array(_el, struct ldb_val, val_count);
1648 if (_el->values == NULL) {
1650 return LDB_ERR_OPERATIONS_ERROR;
1652 _el->num_values = val_count;
1656 for (i = 0; i < msg->num_elements; i++) {
1657 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1658 const struct ldb_message_element *tmp_el = &msg->elements[i];
1659 if ((operation == LDB_MODIFY) &&
1660 (LDB_FLAG_MOD_TYPE(tmp_el->flags)
1661 == LDB_FLAG_MOD_DELETE)) {
1664 if (tmp_el->values == NULL || tmp_el->num_values == 0) {
1669 tmp_el->num_values * sizeof(*v));
1670 v += tmp_el->num_values;
1680 * Get the value of a single-valued attribute from an ADDed message. 'val' will only live as
1681 * long as 'msg' and 'original_val' do, and must not be freed.
1683 int dsdb_msg_add_get_single_value(const struct ldb_message *msg,
1684 const char *attr_name,
1685 const struct ldb_val **val)
1687 const struct ldb_message_element *el = NULL;
1690 * The ldb_msg_normalize() call in ldb_request() ensures that
1691 * there is at most one message element for each
1692 * attribute. Thus, we don't need a loop to deal with an
1695 el = ldb_msg_find_element(msg, attr_name);
1700 if (el->num_values != 1) {
1701 return LDB_ERR_CONSTRAINT_VIOLATION;
1704 *val = &el->values[0];
1709 * Get the value of a single-valued attribute after processing a
1710 * message. 'operation' is either LDB_ADD or LDB_MODIFY. 'val' will only live as
1711 * long as 'msg' and 'original_val' do, and must not be freed.
1713 int dsdb_msg_get_single_value(const struct ldb_message *msg,
1714 const char *attr_name,
1715 const struct ldb_val *original_val,
1716 const struct ldb_val **val,
1717 enum ldb_request_type operation)
1723 if (operation == LDB_ADD) {
1724 if (original_val != NULL) {
1725 /* This is an error on the caller's part. */
1726 return LDB_ERR_CONSTRAINT_VIOLATION;
1728 return dsdb_msg_add_get_single_value(msg, attr_name, val);
1731 SMB_ASSERT(operation == LDB_MODIFY);
1733 *val = original_val;
1735 for (idx = 0; idx < msg->num_elements; ++idx) {
1736 const struct ldb_message_element *el = &msg->elements[idx];
1738 if (ldb_attr_cmp(el->name, attr_name) != 0) {
1742 switch (el->flags & LDB_FLAG_MOD_MASK) {
1743 case LDB_FLAG_MOD_ADD:
1744 if (el->num_values != 1) {
1745 return LDB_ERR_CONSTRAINT_VIOLATION;
1748 return LDB_ERR_CONSTRAINT_VIOLATION;
1751 *val = &el->values[0];
1755 case LDB_FLAG_MOD_REPLACE:
1756 if (el->num_values > 1) {
1757 return LDB_ERR_CONSTRAINT_VIOLATION;
1760 *val = el->num_values ? &el->values[0] : NULL;
1764 case LDB_FLAG_MOD_DELETE:
1765 if (el->num_values > 1) {
1766 return LDB_ERR_CONSTRAINT_VIOLATION;
1770 * If a value was specified for the delete, we don't
1771 * bother checking it matches the value we currently
1772 * have. Any mismatch will be caught later (e.g. in
1773 * ldb_kv_modify_internal).
1786 * This function determines the (last) structural or 88 object class of a passed
1787 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1788 * Without schema this does not work and hence NULL is returned.
1790 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1791 const struct ldb_message_element *element)
1793 const struct dsdb_class *last_class;
1795 if (schema == NULL) {
1799 if (element->num_values == 0) {
1803 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1804 &element->values[element->num_values-1]);
1805 if (last_class == NULL) {
1808 if (last_class->objectClassCategory > 1) {
1815 const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1816 const struct ldb_message *msg)
1818 struct ldb_message_element *oc_el;
1820 oc_el = ldb_msg_find_element(msg, "objectClass");
1825 return dsdb_get_last_structural_class(schema, oc_el);
1829 Get the parent class of an objectclass, or NULL if none exists.
1831 const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
1832 const struct dsdb_class *objectclass)
1834 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
1838 if (objectclass->subClassOf == NULL) {
1842 return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
1846 Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
1847 two objectclasses must originate from the same schema, to allow for
1848 pointer-based identity comparison.
1850 bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
1851 const struct dsdb_class *struct_objectclass,
1852 const struct dsdb_class *other_objectclass)
1854 while (struct_objectclass != NULL) {
1855 /* Pointer comparison can be used due to the same schema str. */
1856 if (struct_objectclass == other_objectclass) {
1860 struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
1866 /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1867 cn=Administrator,cn=users,dc=samba,dc=example,dc=com becomes
1868 CN=Administrator,CN=users,DC=samba,DC=example,DC=com
1870 int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1873 char *upper_rdn_attr;
1875 for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1876 /* We need the attribute name in upper case */
1877 upper_rdn_attr = strupper_talloc(dn,
1878 ldb_dn_get_component_name(dn, i));
1879 if (!upper_rdn_attr) {
1880 return ldb_oom(ldb);
1882 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1883 *ldb_dn_get_component_val(dn, i));
1884 talloc_free(upper_rdn_attr);
1885 if (ret != LDB_SUCCESS) {
1893 * Make most specific objectCategory for the objectClass of passed object
1894 * NOTE: In this implementation we count that it is called on already
1895 * verified objectClass attribute value. See objectclass.c thorough
1896 * implementation for all the magic that involves
1898 * @param ldb ldb context
1899 * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1900 * Hence leave the responsibility to the caller.
1901 * @param obj AD object to determine objectCategory for
1902 * @param mem_ctx Memory context - usually it is obj actually
1903 * @param pobjectcategory location to store found objectCategory
1905 * @return LDB_SUCCESS or error including out of memory error
1907 int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1908 const struct ldb_message *obj,
1909 TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1911 const struct dsdb_class *objectclass;
1912 struct ldb_message_element *objectclass_element;
1913 struct dsdb_extended_dn_store_format *dn_format;
1915 objectclass_element = ldb_msg_find_element(obj, "objectClass");
1916 if (!objectclass_element) {
1917 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1918 ldb_dn_get_linearized(obj->dn));
1919 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1921 if (objectclass_element->num_values == 0) {
1922 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1923 ldb_dn_get_linearized(obj->dn));
1924 return LDB_ERR_CONSTRAINT_VIOLATION;
1928 * Get the new top-most structural object class and check for
1929 * unrelated structural classes
1931 objectclass = dsdb_get_last_structural_class(schema,
1932 objectclass_element);
1933 if (objectclass == NULL) {
1934 ldb_asprintf_errstring(ldb,
1935 "Failed to find a structural class for %s",
1936 ldb_dn_get_linearized(obj->dn));
1937 return LDB_ERR_UNWILLING_TO_PERFORM;
1940 dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1941 struct dsdb_extended_dn_store_format);
1942 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1943 /* Strip off extended components */
1944 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1945 objectclass->defaultObjectCategory);
1946 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1949 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1952 if (*pobjectcategory == NULL) {
1953 return ldb_oom(ldb);
1960 * Remove all password related attributes.
1962 void dsdb_remove_password_related_attrs(struct ldb_message *msg,
1966 ldb_msg_remove_attr(msg, "userPassword");
1968 ldb_msg_remove_attr(msg, "clearTextPassword");
1969 ldb_msg_remove_attr(msg, "unicodePwd");
1970 ldb_msg_remove_attr(msg, "ntPwdHistory");
1971 ldb_msg_remove_attr(msg, "dBCSPwd");
1972 ldb_msg_remove_attr(msg, "lmPwdHistory");
1973 ldb_msg_remove_attr(msg, "supplementalCredentials");
1974 ldb_msg_remove_attr(msg, "pwdLastSet");