s4-dsdb: Make most specific objectCategory for an object
[Samba.git] / source4 / dsdb / samdb / ldb_modules / util.c
blob4c81a1dd3280b16f5449fce20e578e50e0f5cce1
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 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;
190 talloc_free(req);
191 if (ret == LDB_SUCCESS) {
192 *_res = talloc_steal(mem_ctx, res);
194 talloc_free(tmp_ctx);
195 return ret;
199 search for attrs in the modules below
201 int dsdb_module_search(struct ldb_module *module,
202 TALLOC_CTX *mem_ctx,
203 struct ldb_result **_res,
204 struct ldb_dn *basedn, enum ldb_scope scope,
205 const char * const *attrs,
206 int dsdb_flags,
207 struct ldb_request *parent,
208 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
210 int ret;
211 TALLOC_CTX *tmp_ctx;
212 va_list ap;
213 char *expression;
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);
221 if (format) {
222 va_start(ap, format);
223 expression = talloc_vasprintf(tmp_ctx, format, ap);
224 va_end(ap);
226 if (!expression) {
227 talloc_free(tmp_ctx);
228 return ldb_oom(ldb_module_get_ctx(module));
230 } else {
231 expression = NULL;
234 tree = ldb_parse_tree(tmp_ctx, expression);
235 if (tree == NULL) {
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,
243 mem_ctx,
244 _res,
245 basedn,
246 scope,
247 tree,
248 attrs,
249 dsdb_flags,
250 parent);
252 talloc_free(tmp_ctx);
253 return ret;
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);
266 int ret;
268 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
269 attrs,
270 DSDB_FLAG_NEXT_MODULE |
271 DSDB_SEARCH_SHOW_RECYCLED |
272 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
273 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
274 parent,
275 "objectGUID=%s", GUID_string(tmp_ctx, guid));
276 if (ret != LDB_SUCCESS) {
277 talloc_free(tmp_ctx);
278 return ret;
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);
294 return LDB_SUCCESS;
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);
306 int ret;
307 NTSTATUS status;
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,
313 parent);
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);
318 return ret;
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);
328 return LDB_SUCCESS;
333 a ldb_extended request operating on modules below the
334 current module
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,
340 TALLOC_CTX *mem_ctx,
341 struct ldb_result **_res,
342 const char* oid, void* data,
343 uint32_t dsdb_flags,
344 struct ldb_request *parent)
346 struct ldb_request *req;
347 int ret;
348 struct ldb_context *ldb = ldb_module_get_ctx(module);
349 TALLOC_CTX *tmp_ctx = talloc_new(module);
350 struct ldb_result *res;
352 if (_res != NULL) {
353 (*_res) = NULL;
356 res = talloc_zero(tmp_ctx, struct ldb_result);
357 if (!res) {
358 talloc_free(tmp_ctx);
359 return ldb_oom(ldb_module_get_ctx(module));
362 ret = ldb_build_extended_req(&req, ldb,
363 tmp_ctx,
364 oid,
365 data,
366 NULL,
367 res, ldb_extended_default_callback,
368 parent);
370 LDB_REQ_SET_LOCATION(req);
371 if (ret != LDB_SUCCESS) {
372 talloc_free(tmp_ctx);
373 return ret;
376 ret = dsdb_request_add_controls(req, dsdb_flags);
377 if (ret != LDB_SUCCESS) {
378 talloc_free(tmp_ctx);
379 return ret;
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);
391 } else {
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);
405 return ret;
410 a ldb_modify request operating on modules below the
411 current module
413 int dsdb_module_modify(struct ldb_module *module,
414 const struct ldb_message *message,
415 uint32_t dsdb_flags,
416 struct ldb_request *parent)
418 struct ldb_request *mod_req;
419 int ret;
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);
425 if (!res) {
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,
431 message,
432 NULL,
433 res,
434 ldb_modify_default_callback,
435 parent);
436 LDB_REQ_SET_LOCATION(mod_req);
437 if (ret != LDB_SUCCESS) {
438 talloc_free(tmp_ctx);
439 return ret;
442 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
443 if (ret != LDB_SUCCESS) {
444 talloc_free(tmp_ctx);
445 return ret;
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);
457 } else {
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);
467 return ret;
473 a ldb_rename request operating on modules below the
474 current module
476 int dsdb_module_rename(struct ldb_module *module,
477 struct ldb_dn *olddn, struct ldb_dn *newdn,
478 uint32_t dsdb_flags,
479 struct ldb_request *parent)
481 struct ldb_request *req;
482 int ret;
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);
488 if (!res) {
489 talloc_free(tmp_ctx);
490 return ldb_oom(ldb_module_get_ctx(module));
493 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
494 olddn,
495 newdn,
496 NULL,
497 res,
498 ldb_modify_default_callback,
499 parent);
500 LDB_REQ_SET_LOCATION(req);
501 if (ret != LDB_SUCCESS) {
502 talloc_free(tmp_ctx);
503 return ret;
506 ret = dsdb_request_add_controls(req, dsdb_flags);
507 if (ret != LDB_SUCCESS) {
508 talloc_free(tmp_ctx);
509 return ret;
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);
521 } else {
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);
531 return ret;
535 a ldb_add request operating on modules below the
536 current module
538 int dsdb_module_add(struct ldb_module *module,
539 const struct ldb_message *message,
540 uint32_t dsdb_flags,
541 struct ldb_request *parent)
543 struct ldb_request *req;
544 int ret;
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);
550 if (!res) {
551 talloc_free(tmp_ctx);
552 return ldb_oom(ldb_module_get_ctx(module));
555 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
556 message,
557 NULL,
558 res,
559 ldb_modify_default_callback,
560 parent);
561 LDB_REQ_SET_LOCATION(req);
562 if (ret != LDB_SUCCESS) {
563 talloc_free(tmp_ctx);
564 return ret;
567 ret = dsdb_request_add_controls(req, dsdb_flags);
568 if (ret != LDB_SUCCESS) {
569 talloc_free(tmp_ctx);
570 return ret;
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);
582 } else {
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);
592 return ret;
596 a ldb_delete request operating on modules below the
597 current module
599 int dsdb_module_del(struct ldb_module *module,
600 struct ldb_dn *dn,
601 uint32_t dsdb_flags,
602 struct ldb_request *parent)
604 struct ldb_request *req;
605 int ret;
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);
611 if (!res) {
612 talloc_free(tmp_ctx);
613 return ldb_oom(ldb);
616 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
618 NULL,
619 res,
620 ldb_modify_default_callback,
621 parent);
622 LDB_REQ_SET_LOCATION(req);
623 if (ret != LDB_SUCCESS) {
624 talloc_free(tmp_ctx);
625 return ret;
628 ret = dsdb_request_add_controls(req, dsdb_flags);
629 if (ret != LDB_SUCCESS) {
630 talloc_free(tmp_ctx);
631 return ret;
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);
643 } else {
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);
653 return ret;
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;
666 unsigned int i;
668 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
669 el->num_values < 2) {
670 return LDB_SUCCESS;
673 for (i=0; i<el->num_values; i++) {
674 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
675 if (found_active) {
676 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
678 found_active = true;
682 return LDB_SUCCESS;
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)
696 TALLOC_CTX *tmp_ctx;
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};
702 int ret;
703 unsigned int i;
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;
747 break;
751 talloc_free(tmp_ctx);
752 return LDB_SUCCESS;
756 find the NTDS GUID from a computers DN record
758 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
759 TALLOC_CTX *mem_ctx,
760 struct ldb_dn *computer_dn,
761 struct GUID *ntds_guid,
762 struct ldb_request *parent)
764 int ret;
765 struct ldb_dn *dn;
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) {
772 return ret;
775 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
776 talloc_free(dn);
777 return LDB_ERR_OPERATIONS_ERROR;
780 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
781 talloc_free(dn);
782 return ret;
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;
794 int ret;
796 attrs[0] = attribute;
797 attrs[1] = NULL;
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) {
802 return ret;
805 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
806 mem_ctx, res->msgs[0], attribute);
807 if (!*dn) {
808 ldb_reset_err_string(ldb_module_get_ctx(module));
809 talloc_free(res);
810 return LDB_ERR_NO_SUCH_ATTRIBUTE;
813 talloc_free(res);
814 return LDB_SUCCESS;
818 find the RID Manager$ DN via the rIDManagerReference attribute in the
819 base DN
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;
849 int ret;
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);
855 if (!res) {
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"),
862 LDB_SCOPE_BASE,
863 NULL, NULL,
864 NULL,
865 res, ldb_search_default_callback,
866 parent);
867 LDB_REQ_SET_LOCATION(req);
868 if (ret != LDB_SUCCESS) {
869 talloc_free(tmp_ctx);
870 return ret;
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;
879 p_ctrl->dn = dn;
882 ret = ldb_request_add_control(req,
883 DSDB_CONTROL_CURRENT_PARTITION_OID,
884 false, p_ctrl);
885 if (ret != LDB_SUCCESS) {
886 talloc_free(tmp_ctx);
887 return ret;
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 */
900 *uSN = 0;
901 talloc_free(tmp_ctx);
902 ldb_reset_err_string(ldb);
903 return LDB_SUCCESS;
906 if (ret != LDB_SUCCESS) {
907 talloc_free(tmp_ctx);
908 return ret;
911 if (res->count != 1) {
912 *uSN = 0;
913 if (urgent_uSN) {
914 *urgent_uSN = 0;
916 } else {
917 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
918 if (urgent_uSN) {
919 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
923 talloc_free(tmp_ctx);
925 return LDB_SUCCESS;
929 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
930 partition
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;
940 int ret;
941 struct ldb_result *res;
943 msg = ldb_msg_new(module);
944 if (msg == NULL) {
945 return ldb_module_oom(module);
948 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
949 if (msg->dn == NULL) {
950 talloc_free(msg);
951 return ldb_operr(ldb_module_get_ctx(module));
954 res = talloc_zero(msg, struct ldb_result);
955 if (!res) {
956 talloc_free(msg);
957 return ldb_module_oom(module);
960 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
961 if (ret != LDB_SUCCESS) {
962 talloc_free(msg);
963 return ret;
965 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
967 /* urgent_uSN is optional so may not be stored */
968 if (urgent_uSN) {
969 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
970 urgent_uSN);
971 if (ret != LDB_SUCCESS) {
972 talloc_free(msg);
973 return ret;
975 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
979 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
980 if (p_ctrl == NULL) {
981 talloc_free(msg);
982 return ldb_oom(ldb);
984 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
985 p_ctrl->dn = dn;
986 ret = ldb_build_mod_req(&req, ldb, msg,
987 msg,
988 NULL,
989 res,
990 ldb_modify_default_callback,
991 parent);
992 LDB_REQ_SET_LOCATION(req);
993 again:
994 if (ret != LDB_SUCCESS) {
995 talloc_free(msg);
996 return ret;
999 ret = ldb_request_add_control(req,
1000 DSDB_CONTROL_CURRENT_PARTITION_OID,
1001 false, p_ctrl);
1002 if (ret != LDB_SUCCESS) {
1003 talloc_free(msg);
1004 return ret;
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,
1015 msg,
1016 NULL,
1017 res,
1018 ldb_modify_default_callback,
1019 parent);
1020 LDB_REQ_SET_LOCATION(req);
1021 goto again;
1024 talloc_free(msg);
1026 return ret;
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;
1052 int ret;
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;
1062 return LDB_SUCCESS;
1065 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1066 struct ldb_message *msg,
1067 const char *attr,
1068 const int32_t *old_val,
1069 const int32_t *new_val)
1071 struct ldb_message_element *el;
1072 int ret;
1073 char *vstring;
1075 if (old_val) {
1076 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1077 if (ret != LDB_SUCCESS) {
1078 return ret;
1080 el->num_values = 1;
1081 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1082 if (!el->values) {
1083 return ldb_module_oom(module);
1085 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1086 if (!vstring) {
1087 return ldb_module_oom(module);
1089 *el->values = data_blob_string_const(vstring);
1092 if (new_val) {
1093 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1094 if (ret != LDB_SUCCESS) {
1095 return ret;
1097 el->num_values = 1;
1098 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1099 if (!el->values) {
1100 return ldb_module_oom(module);
1102 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1103 if (!vstring) {
1104 return ldb_module_oom(module);
1106 *el->values = data_blob_string_const(vstring);
1109 return LDB_SUCCESS;
1112 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1113 struct ldb_message *msg,
1114 const char *attr,
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,
1125 const char *attr,
1126 const int64_t *old_val,
1127 const int64_t *new_val)
1129 struct ldb_message_element *el;
1130 int ret;
1131 char *vstring;
1133 if (old_val) {
1134 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1135 if (ret != LDB_SUCCESS) {
1136 return ret;
1138 el->num_values = 1;
1139 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1140 if (!el->values) {
1141 return ldb_module_oom(module);
1143 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1144 if (!vstring) {
1145 return ldb_module_oom(module);
1147 *el->values = data_blob_string_const(vstring);
1150 if (new_val) {
1151 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1152 if (ret != LDB_SUCCESS) {
1153 return ret;
1155 el->num_values = 1;
1156 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1157 if (!el->values) {
1158 return ldb_module_oom(module);
1160 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1161 if (!vstring) {
1162 return ldb_module_oom(module);
1164 *el->values = data_blob_string_const(vstring);
1167 return LDB_SUCCESS;
1170 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1171 struct ldb_message *msg,
1172 const char *attr,
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,
1185 struct ldb_dn *dn,
1186 const char *attr,
1187 const int32_t *old_val,
1188 const int32_t *new_val,
1189 struct ldb_request *parent)
1191 struct ldb_message *msg;
1192 int ret;
1194 msg = ldb_msg_new(module);
1195 msg->dn = dn;
1197 ret = dsdb_msg_constrainted_update_int32(module,
1198 msg, attr,
1199 old_val,
1200 new_val);
1201 if (ret != LDB_SUCCESS) {
1202 talloc_free(msg);
1203 return ret;
1206 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1207 talloc_free(msg);
1208 return ret;
1211 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1212 struct ldb_dn *dn,
1213 const char *attr,
1214 const uint32_t *old_val,
1215 const uint32_t *new_val,
1216 struct ldb_request *parent)
1218 return dsdb_module_constrainted_update_int32(module, dn, attr,
1219 (const int32_t *)old_val,
1220 (const int32_t *)new_val, parent);
1224 update an int64 attribute safely via a constrained delete/add
1226 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1227 struct ldb_dn *dn,
1228 const char *attr,
1229 const int64_t *old_val,
1230 const int64_t *new_val,
1231 struct ldb_request *parent)
1233 struct ldb_message *msg;
1234 int ret;
1236 msg = ldb_msg_new(module);
1237 msg->dn = dn;
1239 ret = dsdb_msg_constrainted_update_int64(module,
1240 msg, attr,
1241 old_val,
1242 new_val);
1243 if (ret != LDB_SUCCESS) {
1244 talloc_free(msg);
1245 return ret;
1248 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1249 talloc_free(msg);
1250 return ret;
1253 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1254 struct ldb_dn *dn,
1255 const char *attr,
1256 const uint64_t *old_val,
1257 const uint64_t *new_val,
1258 struct ldb_request *parent)
1260 return dsdb_module_constrainted_update_int64(module, dn, attr,
1261 (const int64_t *)old_val,
1262 (const int64_t *)new_val,
1263 parent);
1267 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1268 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1270 int ret;
1271 struct ldb_dn *new_dn;
1272 struct ldb_context *ldb = ldb_module_get_ctx(module);
1273 static const char *attrs[] = { "dSHeuristics", NULL };
1274 struct ldb_result *res;
1276 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1277 if (!ldb_dn_add_child_fmt(new_dn,
1278 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1279 talloc_free(new_dn);
1280 return NULL;
1282 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1283 new_dn,
1284 attrs,
1285 DSDB_FLAG_NEXT_MODULE,
1286 parent);
1287 if (ret == LDB_SUCCESS && res->count == 1) {
1288 talloc_free(new_dn);
1289 return ldb_msg_find_ldb_val(res->msgs[0],
1290 "dSHeuristics");
1292 talloc_free(new_dn);
1293 return NULL;
1296 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1298 TALLOC_CTX *tmp_ctx = talloc_new(module);
1299 bool result;
1300 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1301 tmp_ctx, parent);
1302 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1303 result = true;
1304 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1305 result = false;
1306 } else {
1307 result = true;
1310 talloc_free(tmp_ctx);
1311 return result;
1314 bool dsdb_user_password_support(struct ldb_module *module,
1315 TALLOC_CTX *mem_ctx,
1316 struct ldb_request *parent)
1318 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1319 bool result;
1320 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1321 tmp_ctx,
1322 parent);
1323 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1324 result = false;
1325 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1326 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1327 result = false;
1328 } else {
1329 result = true;
1332 talloc_free(tmp_ctx);
1333 return result;
1337 show the chain of requests, useful for debugging async requests
1339 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1341 char *s = ldb_module_call_chain(req, req);
1342 DEBUG(level, ("%s\n", s));
1343 talloc_free(s);
1347 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1348 * performing a modify operation.
1350 * In order that the constraint checking by the "objectclass_attrs" LDB module
1351 * does work properly, the change request should remain similar or only be
1352 * enhanced (no other modifications as deletions, variations).
1354 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1355 const char *attr_name,
1356 enum ldb_request_type operation)
1358 struct ldb_message_element *el = NULL;
1359 unsigned int i;
1361 /* We've to walk over all modification entries and consider the last
1362 * non-delete one which belongs to "attr_name".
1364 * If "el" is NULL afterwards then that means there was no interesting
1365 * change entry. */
1366 for (i = 0; i < msg->num_elements; i++) {
1367 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1368 if ((operation == LDB_MODIFY) &&
1369 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1370 == LDB_FLAG_MOD_DELETE)) {
1371 continue;
1373 el = &msg->elements[i];
1377 return el;
1381 * This function determines the (last) structural or 88 object class of a passed
1382 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1383 * Without schema this does not work and hence NULL is returned.
1385 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1386 const struct ldb_message_element *element)
1388 const struct dsdb_class *last_class;
1390 if (schema == NULL) {
1391 return NULL;
1394 if (element->num_values == 0) {
1395 return NULL;
1398 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1399 &element->values[element->num_values-1]);
1400 if (last_class == NULL) {
1401 return NULL;
1403 if (last_class->objectClassCategory > 1) {
1404 return NULL;
1407 return last_class;
1410 const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1411 const struct ldb_message *msg)
1413 struct ldb_message_element *oc_el;
1415 oc_el = ldb_msg_find_element(msg, "objectClass");
1416 if (!oc_el) {
1417 return NULL;
1420 return dsdb_get_last_structural_class(schema, oc_el);
1423 /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1424 cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
1425 CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
1427 int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1429 int i, ret;
1430 char *upper_rdn_attr;
1432 for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1433 /* We need the attribute name in upper case */
1434 upper_rdn_attr = strupper_talloc(dn,
1435 ldb_dn_get_component_name(dn, i));
1436 if (!upper_rdn_attr) {
1437 return ldb_oom(ldb);
1439 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1440 *ldb_dn_get_component_val(dn, i));
1441 talloc_free(upper_rdn_attr);
1442 if (ret != LDB_SUCCESS) {
1443 return ret;
1446 return LDB_SUCCESS;
1450 * Make most specific objectCategory for the objectClass of passed object
1451 * NOTE: In this implementation we count that it is called on already
1452 * verified objectClass attribute value. See objectclass.c thorough
1453 * implementation for all the magic that involves
1455 * @param ldb ldb context
1456 * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1457 * Hence leave the responsibility to the caller.
1458 * @param obj AD object to determint objectCategory for
1459 * @param mem_ctx Memory context - usually it is obj actually
1460 * @param pobjectcategory location to store found objectCategory
1462 * @return LDB_SUCCESS or error including out of memory error
1464 int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1465 struct ldb_message *obj,
1466 TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1468 const struct dsdb_class *objectclass;
1469 struct ldb_message_element *objectclass_element;
1470 struct dsdb_extended_dn_store_format *dn_format;
1472 objectclass_element = ldb_msg_find_element(obj, "objectClass");
1473 if (!objectclass_element) {
1474 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1475 ldb_dn_get_linearized(obj->dn));
1476 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1478 if (objectclass_element->num_values == 0) {
1479 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1480 ldb_dn_get_linearized(obj->dn));
1481 return LDB_ERR_CONSTRAINT_VIOLATION;
1485 * Get the new top-most structural object class and check for
1486 * unrelated structural classes
1488 objectclass = dsdb_get_last_structural_class(schema,
1489 objectclass_element);
1490 if (objectclass == NULL) {
1491 ldb_asprintf_errstring(ldb,
1492 "Failed to find a structural class for %s",
1493 ldb_dn_get_linearized(obj->dn));
1494 return LDB_ERR_UNWILLING_TO_PERFORM;
1497 dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1498 struct dsdb_extended_dn_store_format);
1499 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1500 /* Strip off extended components */
1501 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1502 objectclass->defaultObjectCategory);
1503 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1504 talloc_free(dn);
1505 } else {
1506 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1509 if (*pobjectcategory == NULL) {
1510 return ldb_oom(ldb);
1513 return LDB_SUCCESS;