s3:smbd: consistently use talloc_tos() memory for rpc_pipe_open_interface()
[Samba.git] / source4 / dsdb / samdb / ldb_modules / util.c
blob36d35b7094a0c60c68d86a753bf9a082f6332ebb
1 /*
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/>.
23 #include "includes.h"
24 #include "ldb.h"
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,
36 TALLOC_CTX *mem_ctx,
37 struct ldb_result **_res,
38 struct ldb_dn *basedn,
39 const char * const *attrs,
40 uint32_t dsdb_flags,
41 struct ldb_request *parent)
43 int ret;
44 struct ldb_request *req;
45 TALLOC_CTX *tmp_ctx;
46 struct ldb_result *res;
48 tmp_ctx = talloc_new(mem_ctx);
50 res = talloc_zero(tmp_ctx, struct ldb_result);
51 if (!res) {
52 talloc_free(tmp_ctx);
53 return ldb_oom(ldb_module_get_ctx(module));
56 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
57 basedn,
58 LDB_SCOPE_BASE,
59 NULL,
60 attrs,
61 NULL,
62 res,
63 ldb_search_default_callback,
64 parent);
65 LDB_REQ_SET_LOCATION(req);
66 if (ret != LDB_SUCCESS) {
67 talloc_free(tmp_ctx);
68 return ret;
71 ret = dsdb_request_add_controls(req, dsdb_flags);
72 if (ret != LDB_SUCCESS) {
73 talloc_free(tmp_ctx);
74 return ret;
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);
86 } else {
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) {
96 talloc_free(tmp_ctx);
97 return ret;
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);
106 } else {
107 *_res = talloc_steal(mem_ctx, res);
109 talloc_free(tmp_ctx);
110 return ret;
113 int dsdb_module_search_tree(struct ldb_module *module,
114 TALLOC_CTX *mem_ctx,
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,
120 int dsdb_flags,
121 struct ldb_request *parent)
123 int ret;
124 struct ldb_request *req;
125 TALLOC_CTX *tmp_ctx;
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);
134 if (!res) {
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,
140 basedn,
141 scope,
142 tree,
143 attrs,
144 NULL,
145 res,
146 ldb_search_default_callback,
147 parent);
148 LDB_REQ_SET_LOCATION(req);
149 if (ret != LDB_SUCCESS) {
150 talloc_free(tmp_ctx);
151 return ret;
154 ret = dsdb_request_add_controls(req, dsdb_flags);
155 if (ret != LDB_SUCCESS) {
156 talloc_free(tmp_ctx);
157 return ret;
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);
168 } else {
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;
189 talloc_free(req);
190 if (ret == LDB_SUCCESS) {
191 *_res = talloc_steal(mem_ctx, res);
193 talloc_free(tmp_ctx);
194 return ret;
198 search for attrs in the modules below
200 int dsdb_module_search(struct ldb_module *module,
201 TALLOC_CTX *mem_ctx,
202 struct ldb_result **_res,
203 struct ldb_dn *basedn, enum ldb_scope scope,
204 const char * const *attrs,
205 int dsdb_flags,
206 struct ldb_request *parent,
207 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
209 int ret;
210 TALLOC_CTX *tmp_ctx;
211 va_list ap;
212 char *expression;
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);
220 if (format) {
221 va_start(ap, format);
222 expression = talloc_vasprintf(tmp_ctx, format, ap);
223 va_end(ap);
225 if (!expression) {
226 talloc_free(tmp_ctx);
227 return ldb_oom(ldb_module_get_ctx(module));
229 } else {
230 expression = NULL;
233 tree = ldb_parse_tree(tmp_ctx, expression);
234 if (tree == NULL) {
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,
242 mem_ctx,
243 _res,
244 basedn,
245 scope,
246 tree,
247 attrs,
248 dsdb_flags,
249 parent);
251 talloc_free(tmp_ctx);
252 return ret;
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);
265 int ret;
267 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
268 attrs,
269 DSDB_FLAG_NEXT_MODULE |
270 DSDB_SEARCH_SHOW_RECYCLED |
271 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
272 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
273 parent,
274 "objectGUID=%s", GUID_string(tmp_ctx, guid));
275 if (ret != LDB_SUCCESS) {
276 talloc_free(tmp_ctx);
277 return ret;
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);
293 return LDB_SUCCESS;
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);
305 int ret;
306 NTSTATUS status;
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,
312 parent);
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);
317 return ret;
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);
327 return LDB_SUCCESS;
332 a ldb_extended request operating on modules below the
333 current module
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,
339 TALLOC_CTX *mem_ctx,
340 struct ldb_result **_res,
341 const char* oid, void* data,
342 uint32_t dsdb_flags,
343 struct ldb_request *parent)
345 struct ldb_request *req;
346 int ret;
347 struct ldb_context *ldb = ldb_module_get_ctx(module);
348 TALLOC_CTX *tmp_ctx = talloc_new(module);
349 struct ldb_result *res;
351 if (_res != NULL) {
352 (*_res) = NULL;
355 res = talloc_zero(tmp_ctx, struct ldb_result);
356 if (!res) {
357 talloc_free(tmp_ctx);
358 return ldb_oom(ldb_module_get_ctx(module));
361 ret = ldb_build_extended_req(&req, ldb,
362 tmp_ctx,
363 oid,
364 data,
365 NULL,
366 res, ldb_extended_default_callback,
367 parent);
369 LDB_REQ_SET_LOCATION(req);
370 if (ret != LDB_SUCCESS) {
371 talloc_free(tmp_ctx);
372 return ret;
375 ret = dsdb_request_add_controls(req, dsdb_flags);
376 if (ret != LDB_SUCCESS) {
377 talloc_free(tmp_ctx);
378 return ret;
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);
390 } else {
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);
404 return ret;
409 a ldb_modify request operating on modules below the
410 current module
412 int dsdb_module_modify(struct ldb_module *module,
413 const struct ldb_message *message,
414 uint32_t dsdb_flags,
415 struct ldb_request *parent)
417 struct ldb_request *mod_req;
418 int ret;
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);
424 if (!res) {
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,
430 message,
431 NULL,
432 res,
433 ldb_modify_default_callback,
434 parent);
435 LDB_REQ_SET_LOCATION(mod_req);
436 if (ret != LDB_SUCCESS) {
437 talloc_free(tmp_ctx);
438 return ret;
441 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
442 if (ret != LDB_SUCCESS) {
443 talloc_free(tmp_ctx);
444 return ret;
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);
456 } else {
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);
466 return ret;
472 a ldb_rename request operating on modules below the
473 current module
475 int dsdb_module_rename(struct ldb_module *module,
476 struct ldb_dn *olddn, struct ldb_dn *newdn,
477 uint32_t dsdb_flags,
478 struct ldb_request *parent)
480 struct ldb_request *req;
481 int ret;
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);
487 if (!res) {
488 talloc_free(tmp_ctx);
489 return ldb_oom(ldb_module_get_ctx(module));
492 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
493 olddn,
494 newdn,
495 NULL,
496 res,
497 ldb_modify_default_callback,
498 parent);
499 LDB_REQ_SET_LOCATION(req);
500 if (ret != LDB_SUCCESS) {
501 talloc_free(tmp_ctx);
502 return ret;
505 ret = dsdb_request_add_controls(req, dsdb_flags);
506 if (ret != LDB_SUCCESS) {
507 talloc_free(tmp_ctx);
508 return ret;
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);
520 } else {
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);
530 return ret;
534 a ldb_add request operating on modules below the
535 current module
537 int dsdb_module_add(struct ldb_module *module,
538 const struct ldb_message *message,
539 uint32_t dsdb_flags,
540 struct ldb_request *parent)
542 struct ldb_request *req;
543 int ret;
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);
549 if (!res) {
550 talloc_free(tmp_ctx);
551 return ldb_oom(ldb_module_get_ctx(module));
554 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
555 message,
556 NULL,
557 res,
558 ldb_modify_default_callback,
559 parent);
560 LDB_REQ_SET_LOCATION(req);
561 if (ret != LDB_SUCCESS) {
562 talloc_free(tmp_ctx);
563 return ret;
566 ret = dsdb_request_add_controls(req, dsdb_flags);
567 if (ret != LDB_SUCCESS) {
568 talloc_free(tmp_ctx);
569 return ret;
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);
581 } else {
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);
591 return ret;
595 a ldb_delete request operating on modules below the
596 current module
598 int dsdb_module_del(struct ldb_module *module,
599 struct ldb_dn *dn,
600 uint32_t dsdb_flags,
601 struct ldb_request *parent)
603 struct ldb_request *req;
604 int ret;
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);
610 if (!res) {
611 talloc_free(tmp_ctx);
612 return ldb_oom(ldb);
615 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
617 NULL,
618 res,
619 ldb_modify_default_callback,
620 parent);
621 LDB_REQ_SET_LOCATION(req);
622 if (ret != LDB_SUCCESS) {
623 talloc_free(tmp_ctx);
624 return ret;
627 ret = dsdb_request_add_controls(req, dsdb_flags);
628 if (ret != LDB_SUCCESS) {
629 talloc_free(tmp_ctx);
630 return ret;
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);
642 } else {
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);
652 return ret;
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;
665 unsigned int i;
667 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
668 el->num_values < 2) {
669 return LDB_SUCCESS;
672 for (i=0; i<el->num_values; i++) {
673 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
674 if (found_active) {
675 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
677 found_active = true;
681 return LDB_SUCCESS;
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 propogate between the two
693 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
695 TALLOC_CTX *tmp_ctx;
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};
701 int ret;
702 unsigned int i;
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;
746 break;
750 talloc_free(tmp_ctx);
751 return LDB_SUCCESS;
755 find the NTDS GUID from a computers DN record
757 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
758 TALLOC_CTX *mem_ctx,
759 struct ldb_dn *computer_dn,
760 struct GUID *ntds_guid,
761 struct ldb_request *parent)
763 int ret;
764 struct ldb_dn *dn;
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) {
771 return ret;
774 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
775 talloc_free(dn);
776 return LDB_ERR_OPERATIONS_ERROR;
779 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
780 talloc_free(dn);
781 return ret;
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;
793 int ret;
795 attrs[0] = attribute;
796 attrs[1] = NULL;
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) {
801 return ret;
804 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
805 mem_ctx, res->msgs[0], attribute);
806 if (!*dn) {
807 ldb_reset_err_string(ldb_module_get_ctx(module));
808 talloc_free(res);
809 return LDB_ERR_NO_SUCH_ATTRIBUTE;
812 talloc_free(res);
813 return LDB_SUCCESS;
817 find the RID Manager$ DN via the rIDManagerReference attribute in the
818 base DN
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);
835 talloc_steal(up_req, req);
836 return up_req->callback(up_req, ares);
840 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
841 object for a partition
843 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
844 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
846 struct ldb_context *ldb = ldb_module_get_ctx(module);
847 struct ldb_request *req;
848 int ret;
849 TALLOC_CTX *tmp_ctx = talloc_new(module);
850 struct dsdb_control_current_partition *p_ctrl;
851 struct ldb_result *res;
853 res = talloc_zero(tmp_ctx, struct ldb_result);
854 if (!res) {
855 talloc_free(tmp_ctx);
856 return ldb_module_oom(module);
859 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
860 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
861 LDB_SCOPE_BASE,
862 NULL, NULL,
863 NULL,
864 res, ldb_search_default_callback,
865 parent);
866 LDB_REQ_SET_LOCATION(req);
867 if (ret != LDB_SUCCESS) {
868 talloc_free(tmp_ctx);
869 return ret;
872 p_ctrl = talloc(req, struct dsdb_control_current_partition);
873 if (p_ctrl == NULL) {
874 talloc_free(tmp_ctx);
875 return ldb_module_oom(module);
877 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
878 p_ctrl->dn = dn;
881 ret = ldb_request_add_control(req,
882 DSDB_CONTROL_CURRENT_PARTITION_OID,
883 false, p_ctrl);
884 if (ret != LDB_SUCCESS) {
885 talloc_free(tmp_ctx);
886 return ret;
889 /* Run the new request */
890 ret = ldb_next_request(module, req);
892 if (ret == LDB_SUCCESS) {
893 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
896 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
897 /* it hasn't been created yet, which means
898 an implicit value of zero */
899 *uSN = 0;
900 talloc_free(tmp_ctx);
901 ldb_reset_err_string(ldb);
902 return LDB_SUCCESS;
905 if (ret != LDB_SUCCESS) {
906 talloc_free(tmp_ctx);
907 return ret;
910 if (res->count != 1) {
911 *uSN = 0;
912 if (urgent_uSN) {
913 *urgent_uSN = 0;
915 } else {
916 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
917 if (urgent_uSN) {
918 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
922 talloc_free(tmp_ctx);
924 return LDB_SUCCESS;
928 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
929 partition
931 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
932 uint64_t uSN, uint64_t urgent_uSN,
933 struct ldb_request *parent)
935 struct ldb_context *ldb = ldb_module_get_ctx(module);
936 struct ldb_request *req;
937 struct ldb_message *msg;
938 struct dsdb_control_current_partition *p_ctrl;
939 int ret;
940 struct ldb_result *res;
942 msg = ldb_msg_new(module);
943 if (msg == NULL) {
944 return ldb_module_oom(module);
947 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
948 if (msg->dn == NULL) {
949 talloc_free(msg);
950 return ldb_operr(ldb_module_get_ctx(module));
953 res = talloc_zero(msg, struct ldb_result);
954 if (!res) {
955 talloc_free(msg);
956 return ldb_module_oom(module);
959 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
960 if (ret != LDB_SUCCESS) {
961 talloc_free(msg);
962 return ret;
964 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
966 /* urgent_uSN is optional so may not be stored */
967 if (urgent_uSN) {
968 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
969 urgent_uSN);
970 if (ret != LDB_SUCCESS) {
971 talloc_free(msg);
972 return ret;
974 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
978 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
979 if (p_ctrl == NULL) {
980 talloc_free(msg);
981 return ldb_oom(ldb);
983 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
984 p_ctrl->dn = dn;
985 ret = ldb_build_mod_req(&req, ldb, msg,
986 msg,
987 NULL,
988 res,
989 ldb_modify_default_callback,
990 parent);
991 LDB_REQ_SET_LOCATION(req);
992 again:
993 if (ret != LDB_SUCCESS) {
994 talloc_free(msg);
995 return ret;
998 ret = ldb_request_add_control(req,
999 DSDB_CONTROL_CURRENT_PARTITION_OID,
1000 false, p_ctrl);
1001 if (ret != LDB_SUCCESS) {
1002 talloc_free(msg);
1003 return ret;
1006 /* Run the new request */
1007 ret = ldb_next_request(module, req);
1009 if (ret == LDB_SUCCESS) {
1010 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1012 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1013 ret = ldb_build_add_req(&req, ldb, msg,
1014 msg,
1015 NULL,
1016 res,
1017 ldb_modify_default_callback,
1018 parent);
1019 LDB_REQ_SET_LOCATION(req);
1020 goto again;
1023 talloc_free(msg);
1025 return ret;
1028 bool dsdb_module_am_system(struct ldb_module *module)
1030 struct ldb_context *ldb = ldb_module_get_ctx(module);
1031 struct auth_session_info *session_info
1032 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1033 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1036 bool dsdb_module_am_administrator(struct ldb_module *module)
1038 struct ldb_context *ldb = ldb_module_get_ctx(module);
1039 struct auth_session_info *session_info
1040 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
1041 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1045 check if the recyclebin is enabled
1047 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1049 struct ldb_context *ldb = ldb_module_get_ctx(module);
1050 struct GUID recyclebin_guid;
1051 int ret;
1053 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1055 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1056 if (ret != LDB_SUCCESS) {
1057 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1058 return ret;
1061 return LDB_SUCCESS;
1064 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1065 struct ldb_message *msg,
1066 const char *attr,
1067 const int32_t *old_val,
1068 const int32_t *new_val)
1070 struct ldb_message_element *el;
1071 int ret;
1072 char *vstring;
1074 if (old_val) {
1075 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1076 if (ret != LDB_SUCCESS) {
1077 return ret;
1079 el->num_values = 1;
1080 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1081 if (!el->values) {
1082 return ldb_module_oom(module);
1084 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1085 if (!vstring) {
1086 return ldb_module_oom(module);
1088 *el->values = data_blob_string_const(vstring);
1091 if (new_val) {
1092 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1093 if (ret != LDB_SUCCESS) {
1094 return ret;
1096 el->num_values = 1;
1097 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1098 if (!el->values) {
1099 return ldb_module_oom(module);
1101 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1102 if (!vstring) {
1103 return ldb_module_oom(module);
1105 *el->values = data_blob_string_const(vstring);
1108 return LDB_SUCCESS;
1111 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1112 struct ldb_message *msg,
1113 const char *attr,
1114 const uint32_t *old_val,
1115 const uint32_t *new_val)
1117 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1118 (const int32_t *)old_val,
1119 (const int32_t *)new_val);
1122 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1123 struct ldb_message *msg,
1124 const char *attr,
1125 const int64_t *old_val,
1126 const int64_t *new_val)
1128 struct ldb_message_element *el;
1129 int ret;
1130 char *vstring;
1132 if (old_val) {
1133 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1134 if (ret != LDB_SUCCESS) {
1135 return ret;
1137 el->num_values = 1;
1138 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1139 if (!el->values) {
1140 return ldb_module_oom(module);
1142 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1143 if (!vstring) {
1144 return ldb_module_oom(module);
1146 *el->values = data_blob_string_const(vstring);
1149 if (new_val) {
1150 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1151 if (ret != LDB_SUCCESS) {
1152 return ret;
1154 el->num_values = 1;
1155 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1156 if (!el->values) {
1157 return ldb_module_oom(module);
1159 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1160 if (!vstring) {
1161 return ldb_module_oom(module);
1163 *el->values = data_blob_string_const(vstring);
1166 return LDB_SUCCESS;
1169 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1170 struct ldb_message *msg,
1171 const char *attr,
1172 const uint64_t *old_val,
1173 const uint64_t *new_val)
1175 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1176 (const int64_t *)old_val,
1177 (const int64_t *)new_val);
1181 update an int32 attribute safely via a constrained delete/add
1183 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1184 struct ldb_dn *dn,
1185 const char *attr,
1186 const int32_t *old_val,
1187 const int32_t *new_val,
1188 struct ldb_request *parent)
1190 struct ldb_message *msg;
1191 int ret;
1193 msg = ldb_msg_new(module);
1194 if (msg == NULL) {
1195 return ldb_module_oom(module);
1197 msg->dn = dn;
1199 ret = dsdb_msg_constrainted_update_int32(module,
1200 msg, attr,
1201 old_val,
1202 new_val);
1203 if (ret != LDB_SUCCESS) {
1204 talloc_free(msg);
1205 return ret;
1208 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1209 talloc_free(msg);
1210 return ret;
1213 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1214 struct ldb_dn *dn,
1215 const char *attr,
1216 const uint32_t *old_val,
1217 const uint32_t *new_val,
1218 struct ldb_request *parent)
1220 return dsdb_module_constrainted_update_int32(module, dn, attr,
1221 (const int32_t *)old_val,
1222 (const int32_t *)new_val, parent);
1226 update an int64 attribute safely via a constrained delete/add
1228 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1229 struct ldb_dn *dn,
1230 const char *attr,
1231 const int64_t *old_val,
1232 const int64_t *new_val,
1233 struct ldb_request *parent)
1235 struct ldb_message *msg;
1236 int ret;
1238 msg = ldb_msg_new(module);
1239 if (msg == NULL) {
1240 return ldb_module_oom(module);
1242 msg->dn = dn;
1244 ret = dsdb_msg_constrainted_update_int64(module,
1245 msg, attr,
1246 old_val,
1247 new_val);
1248 if (ret != LDB_SUCCESS) {
1249 talloc_free(msg);
1250 return ret;
1253 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1254 talloc_free(msg);
1255 return ret;
1258 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1259 struct ldb_dn *dn,
1260 const char *attr,
1261 const uint64_t *old_val,
1262 const uint64_t *new_val,
1263 struct ldb_request *parent)
1265 return dsdb_module_constrainted_update_int64(module, dn, attr,
1266 (const int64_t *)old_val,
1267 (const int64_t *)new_val,
1268 parent);
1272 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1273 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1275 int ret;
1276 struct ldb_dn *new_dn;
1277 struct ldb_context *ldb = ldb_module_get_ctx(module);
1278 static const char *attrs[] = { "dSHeuristics", NULL };
1279 struct ldb_result *res;
1281 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1282 if (!ldb_dn_add_child_fmt(new_dn,
1283 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1284 talloc_free(new_dn);
1285 return NULL;
1287 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1288 new_dn,
1289 attrs,
1290 DSDB_FLAG_NEXT_MODULE,
1291 parent);
1292 if (ret == LDB_SUCCESS && res->count == 1) {
1293 talloc_free(new_dn);
1294 return ldb_msg_find_ldb_val(res->msgs[0],
1295 "dSHeuristics");
1297 talloc_free(new_dn);
1298 return NULL;
1301 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1303 TALLOC_CTX *tmp_ctx = talloc_new(module);
1304 bool result;
1305 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1306 tmp_ctx, parent);
1307 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1308 result = true;
1309 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1310 result = false;
1311 } else {
1312 result = true;
1315 talloc_free(tmp_ctx);
1316 return result;
1319 bool dsdb_user_password_support(struct ldb_module *module,
1320 TALLOC_CTX *mem_ctx,
1321 struct ldb_request *parent)
1323 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1324 bool result;
1325 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1326 tmp_ctx,
1327 parent);
1328 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1329 result = false;
1330 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1331 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1332 result = false;
1333 } else {
1334 result = true;
1337 talloc_free(tmp_ctx);
1338 return result;
1342 show the chain of requests, useful for debugging async requests
1344 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1346 char *s = ldb_module_call_chain(req, req);
1347 DEBUG(level, ("%s\n", s));
1348 talloc_free(s);
1352 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1353 * performing a modify operation.
1355 * In order that the constraint checking by the "objectclass_attrs" LDB module
1356 * does work properly, the change request should remain similar or only be
1357 * enhanced (no other modifications as deletions, variations).
1359 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1360 const char *attr_name,
1361 enum ldb_request_type operation)
1363 struct ldb_message_element *el = NULL;
1364 unsigned int i;
1366 /* We've to walk over all modification entries and consider the last
1367 * non-delete one which belongs to "attr_name".
1369 * If "el" is NULL afterwards then that means there was no interesting
1370 * change entry. */
1371 for (i = 0; i < msg->num_elements; i++) {
1372 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1373 if ((operation == LDB_MODIFY) &&
1374 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1375 == LDB_FLAG_MOD_DELETE)) {
1376 continue;
1378 el = &msg->elements[i];
1382 return el;
1386 * This function determines the (last) structural or 88 object class of a passed
1387 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1388 * Without schema this does not work and hence NULL is returned.
1390 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1391 const struct ldb_message_element *element)
1393 const struct dsdb_class *last_class;
1395 if (schema == NULL) {
1396 return NULL;
1399 if (element->num_values == 0) {
1400 return NULL;
1403 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1404 &element->values[element->num_values-1]);
1405 if (last_class == NULL) {
1406 return NULL;
1408 if (last_class->objectClassCategory > 1) {
1409 return NULL;
1412 return last_class;
1415 const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1416 const struct ldb_message *msg)
1418 struct ldb_message_element *oc_el;
1420 oc_el = ldb_msg_find_element(msg, "objectClass");
1421 if (!oc_el) {
1422 return NULL;
1425 return dsdb_get_last_structural_class(schema, oc_el);
1428 /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1429 cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
1430 CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
1432 int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1434 int i, ret;
1435 char *upper_rdn_attr;
1437 for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1438 /* We need the attribute name in upper case */
1439 upper_rdn_attr = strupper_talloc(dn,
1440 ldb_dn_get_component_name(dn, i));
1441 if (!upper_rdn_attr) {
1442 return ldb_oom(ldb);
1444 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1445 *ldb_dn_get_component_val(dn, i));
1446 talloc_free(upper_rdn_attr);
1447 if (ret != LDB_SUCCESS) {
1448 return ret;
1451 return LDB_SUCCESS;
1455 * Make most specific objectCategory for the objectClass of passed object
1456 * NOTE: In this implementation we count that it is called on already
1457 * verified objectClass attribute value. See objectclass.c thorough
1458 * implementation for all the magic that involves
1460 * @param ldb ldb context
1461 * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1462 * Hence leave the responsibility to the caller.
1463 * @param obj AD object to determint objectCategory for
1464 * @param mem_ctx Memory context - usually it is obj actually
1465 * @param pobjectcategory location to store found objectCategory
1467 * @return LDB_SUCCESS or error including out of memory error
1469 int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1470 const struct ldb_message *obj,
1471 TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1473 const struct dsdb_class *objectclass;
1474 struct ldb_message_element *objectclass_element;
1475 struct dsdb_extended_dn_store_format *dn_format;
1477 objectclass_element = ldb_msg_find_element(obj, "objectClass");
1478 if (!objectclass_element) {
1479 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1480 ldb_dn_get_linearized(obj->dn));
1481 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1483 if (objectclass_element->num_values == 0) {
1484 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1485 ldb_dn_get_linearized(obj->dn));
1486 return LDB_ERR_CONSTRAINT_VIOLATION;
1490 * Get the new top-most structural object class and check for
1491 * unrelated structural classes
1493 objectclass = dsdb_get_last_structural_class(schema,
1494 objectclass_element);
1495 if (objectclass == NULL) {
1496 ldb_asprintf_errstring(ldb,
1497 "Failed to find a structural class for %s",
1498 ldb_dn_get_linearized(obj->dn));
1499 return LDB_ERR_UNWILLING_TO_PERFORM;
1502 dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1503 struct dsdb_extended_dn_store_format);
1504 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1505 /* Strip off extended components */
1506 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1507 objectclass->defaultObjectCategory);
1508 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1509 talloc_free(dn);
1510 } else {
1511 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1514 if (*pobjectcategory == NULL) {
1515 return ldb_oom(ldb);
1518 return LDB_SUCCESS;