s4:dsdb: Fix code spelling
[Samba.git] / source4 / dsdb / samdb / ldb_modules / util.c
blob0342da39a94a108b3d662004ae28fdce97810a3c
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"
32 #undef strcasecmp
35 search for attrs on one DN, in the modules below
37 int dsdb_module_search_dn(struct ldb_module *module,
38 TALLOC_CTX *mem_ctx,
39 struct ldb_result **_res,
40 struct ldb_dn *basedn,
41 const char * const *attrs,
42 uint32_t dsdb_flags,
43 struct ldb_request *parent)
45 int ret;
46 struct ldb_request *req;
47 TALLOC_CTX *tmp_ctx;
48 struct ldb_result *res;
50 tmp_ctx = talloc_new(mem_ctx);
52 res = talloc_zero(tmp_ctx, struct ldb_result);
53 if (!res) {
54 talloc_free(tmp_ctx);
55 return ldb_oom(ldb_module_get_ctx(module));
58 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
59 basedn,
60 LDB_SCOPE_BASE,
61 NULL,
62 attrs,
63 NULL,
64 res,
65 ldb_search_default_callback,
66 parent);
67 LDB_REQ_SET_LOCATION(req);
68 if (ret != LDB_SUCCESS) {
69 talloc_free(tmp_ctx);
70 return ret;
73 ret = dsdb_request_add_controls(req, dsdb_flags);
74 if (ret != LDB_SUCCESS) {
75 talloc_free(tmp_ctx);
76 return ret;
79 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
80 ldb_req_mark_trusted(req);
83 /* Run the new request */
84 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
85 ret = ldb_next_request(module, req);
86 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
87 ret = ldb_request(ldb_module_get_ctx(module), req);
88 } else {
89 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
90 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
91 ret = ops->search(module, req);
93 if (ret == LDB_SUCCESS) {
94 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
97 if (ret != LDB_SUCCESS) {
98 talloc_free(tmp_ctx);
99 return ret;
102 if (res->count != 1) {
103 /* we may be reading a DB that does not have the 'check base on search' option... */
104 ret = LDB_ERR_NO_SUCH_OBJECT;
105 ldb_asprintf_errstring(ldb_module_get_ctx(module),
106 "dsdb_module_search_dn: did not find base dn %s (%d results)",
107 ldb_dn_get_linearized(basedn), res->count);
108 } else {
109 *_res = talloc_steal(mem_ctx, res);
111 talloc_free(tmp_ctx);
112 return ret;
115 int dsdb_module_search_tree(struct ldb_module *module,
116 TALLOC_CTX *mem_ctx,
117 struct ldb_result **_res,
118 struct ldb_dn *basedn,
119 enum ldb_scope scope,
120 struct ldb_parse_tree *tree,
121 const char * const *attrs,
122 int dsdb_flags,
123 struct ldb_request *parent)
125 int ret;
126 struct ldb_request *req;
127 TALLOC_CTX *tmp_ctx;
128 struct ldb_result *res;
130 tmp_ctx = talloc_new(mem_ctx);
132 /* cross-partitions searches with a basedn break multi-domain support */
133 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
135 res = talloc_zero(tmp_ctx, struct ldb_result);
136 if (!res) {
137 talloc_free(tmp_ctx);
138 return ldb_oom(ldb_module_get_ctx(module));
141 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
142 basedn,
143 scope,
144 tree,
145 attrs,
146 NULL,
147 res,
148 ldb_search_default_callback,
149 parent);
150 LDB_REQ_SET_LOCATION(req);
151 if (ret != LDB_SUCCESS) {
152 talloc_free(tmp_ctx);
153 return ret;
156 ret = dsdb_request_add_controls(req, dsdb_flags);
157 if (ret != LDB_SUCCESS) {
158 talloc_free(tmp_ctx);
159 return ret;
162 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
163 ldb_req_mark_trusted(req);
166 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
167 ret = ldb_next_request(module, req);
168 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
169 ret = ldb_request(ldb_module_get_ctx(module), req);
170 } else {
171 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
172 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
173 ret = ops->search(module, req);
175 if (ret == LDB_SUCCESS) {
176 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
179 if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
180 if (res->count == 0) {
181 talloc_free(tmp_ctx);
182 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
184 if (res->count != 1) {
185 talloc_free(tmp_ctx);
186 ldb_reset_err_string(ldb_module_get_ctx(module));
187 return LDB_ERR_CONSTRAINT_VIOLATION;
191 talloc_free(req);
192 if (ret == LDB_SUCCESS) {
193 *_res = talloc_steal(mem_ctx, res);
195 talloc_free(tmp_ctx);
196 return ret;
200 search for attrs in the modules below
202 int dsdb_module_search(struct ldb_module *module,
203 TALLOC_CTX *mem_ctx,
204 struct ldb_result **_res,
205 struct ldb_dn *basedn, enum ldb_scope scope,
206 const char * const *attrs,
207 int dsdb_flags,
208 struct ldb_request *parent,
209 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
211 int ret;
212 TALLOC_CTX *tmp_ctx;
213 va_list ap;
214 char *expression;
215 struct ldb_parse_tree *tree;
217 /* cross-partitions searches with a basedn break multi-domain support */
218 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
220 tmp_ctx = talloc_new(mem_ctx);
222 if (format) {
223 va_start(ap, format);
224 expression = talloc_vasprintf(tmp_ctx, format, ap);
225 va_end(ap);
227 if (!expression) {
228 talloc_free(tmp_ctx);
229 return ldb_oom(ldb_module_get_ctx(module));
231 } else {
232 expression = NULL;
235 tree = ldb_parse_tree(tmp_ctx, expression);
236 if (tree == NULL) {
237 talloc_free(tmp_ctx);
238 ldb_set_errstring(ldb_module_get_ctx(module),
239 "Unable to parse search expression");
240 return LDB_ERR_OPERATIONS_ERROR;
243 ret = dsdb_module_search_tree(module,
244 mem_ctx,
245 _res,
246 basedn,
247 scope,
248 tree,
249 attrs,
250 dsdb_flags,
251 parent);
253 talloc_free(tmp_ctx);
254 return ret;
258 find an object given a GUID. This searches across all partitions
260 int dsdb_module_obj_by_guid(struct ldb_module *module,
261 TALLOC_CTX *mem_ctx,
262 struct ldb_message **_msg,
263 const struct GUID *guid,
264 const char * const *attrs,
265 struct ldb_request *parent)
267 struct ldb_result *res;
268 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
269 int ret;
271 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
272 attrs,
273 DSDB_FLAG_NEXT_MODULE |
274 DSDB_SEARCH_SHOW_RECYCLED |
275 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
276 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
277 parent,
278 "objectGUID=%s", GUID_string(tmp_ctx, guid));
279 if (ret != LDB_SUCCESS) {
280 talloc_free(tmp_ctx);
281 return ret;
283 if (res->count == 0) {
284 talloc_free(tmp_ctx);
285 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
287 if (res->count != 1) {
288 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
289 GUID_string(tmp_ctx, guid));
290 talloc_free(tmp_ctx);
291 return LDB_ERR_OPERATIONS_ERROR;
294 *_msg = talloc_steal(mem_ctx, res->msgs[0]);
296 talloc_free(tmp_ctx);
297 return LDB_SUCCESS;
301 find a DN given a GUID. This searches across all partitions
303 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
304 const struct GUID *guid, struct ldb_dn **dn,
305 struct ldb_request *parent)
307 struct ldb_message *msg = NULL;
308 static const char * const attrs[] = { NULL };
309 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
310 int ret;
312 ret = dsdb_module_obj_by_guid(module,
313 tmp_ctx,
314 &msg,
315 guid,
316 attrs,
317 parent);
318 if (ret != LDB_SUCCESS) {
319 talloc_free(tmp_ctx);
320 return ret;
323 *dn = talloc_steal(mem_ctx, msg->dn);
325 talloc_free(tmp_ctx);
326 return LDB_SUCCESS;
330 find a GUID given a DN.
332 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
333 struct ldb_request *parent)
335 static const char * const attrs[] = { NULL };
336 struct ldb_result *res;
337 TALLOC_CTX *tmp_ctx = talloc_new(module);
338 int ret;
339 NTSTATUS status;
341 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
342 DSDB_FLAG_NEXT_MODULE |
343 DSDB_SEARCH_SHOW_RECYCLED |
344 DSDB_SEARCH_SHOW_EXTENDED_DN,
345 parent);
346 if (ret != LDB_SUCCESS) {
347 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
348 ldb_dn_get_linearized(dn));
349 talloc_free(tmp_ctx);
350 return ret;
353 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
354 if (!NT_STATUS_IS_OK(status)) {
355 talloc_free(tmp_ctx);
356 return ldb_operr(ldb_module_get_ctx(module));
359 talloc_free(tmp_ctx);
360 return LDB_SUCCESS;
365 a ldb_extended request operating on modules below the
366 current module
368 Note that this does not automatically start a transaction. If you
369 need a transaction the caller needs to start it as needed.
371 int dsdb_module_extended(struct ldb_module *module,
372 TALLOC_CTX *mem_ctx,
373 struct ldb_result **_res,
374 const char* oid, void* data,
375 uint32_t dsdb_flags,
376 struct ldb_request *parent)
378 struct ldb_request *req;
379 int ret;
380 struct ldb_context *ldb = ldb_module_get_ctx(module);
381 TALLOC_CTX *tmp_ctx = talloc_new(module);
382 struct ldb_result *res;
384 if (_res != NULL) {
385 (*_res) = NULL;
388 res = talloc_zero(tmp_ctx, struct ldb_result);
389 if (!res) {
390 talloc_free(tmp_ctx);
391 return ldb_oom(ldb_module_get_ctx(module));
394 ret = ldb_build_extended_req(&req, ldb,
395 tmp_ctx,
396 oid,
397 data,
398 NULL,
399 res, ldb_extended_default_callback,
400 parent);
402 LDB_REQ_SET_LOCATION(req);
403 if (ret != LDB_SUCCESS) {
404 talloc_free(tmp_ctx);
405 return ret;
408 ret = dsdb_request_add_controls(req, dsdb_flags);
409 if (ret != LDB_SUCCESS) {
410 talloc_free(tmp_ctx);
411 return ret;
414 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
415 ldb_req_mark_trusted(req);
418 /* Run the new request */
419 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
420 ret = ldb_next_request(module, req);
421 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
422 ret = ldb_request(ldb_module_get_ctx(module), req);
423 } else {
424 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
425 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
426 ret = ops->extended(module, req);
428 if (ret == LDB_SUCCESS) {
429 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
432 if (_res != NULL && ret == LDB_SUCCESS) {
433 (*_res) = talloc_steal(mem_ctx, res);
436 talloc_free(tmp_ctx);
437 return ret;
442 a ldb_modify request operating on modules below the
443 current module
445 int dsdb_module_modify(struct ldb_module *module,
446 const struct ldb_message *message,
447 uint32_t dsdb_flags,
448 struct ldb_request *parent)
450 struct ldb_request *mod_req;
451 int ret;
452 struct ldb_context *ldb = ldb_module_get_ctx(module);
453 TALLOC_CTX *tmp_ctx = talloc_new(module);
454 struct ldb_result *res;
456 res = talloc_zero(tmp_ctx, struct ldb_result);
457 if (!res) {
458 talloc_free(tmp_ctx);
459 return ldb_oom(ldb_module_get_ctx(module));
462 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
463 message,
464 NULL,
465 res,
466 ldb_modify_default_callback,
467 parent);
468 LDB_REQ_SET_LOCATION(mod_req);
469 if (ret != LDB_SUCCESS) {
470 talloc_free(tmp_ctx);
471 return ret;
474 ret = dsdb_request_add_controls(mod_req, dsdb_flags);
475 if (ret != LDB_SUCCESS) {
476 talloc_free(tmp_ctx);
477 return ret;
480 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
481 ldb_req_mark_trusted(mod_req);
484 /* Run the new request */
485 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
486 ret = ldb_next_request(module, mod_req);
487 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
488 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
489 } else {
490 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
491 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
492 ret = ops->modify(module, mod_req);
494 if (ret == LDB_SUCCESS) {
495 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
498 talloc_free(tmp_ctx);
499 return ret;
505 a ldb_rename request operating on modules below the
506 current module
508 int dsdb_module_rename(struct ldb_module *module,
509 struct ldb_dn *olddn, struct ldb_dn *newdn,
510 uint32_t dsdb_flags,
511 struct ldb_request *parent)
513 struct ldb_request *req;
514 int ret;
515 struct ldb_context *ldb = ldb_module_get_ctx(module);
516 TALLOC_CTX *tmp_ctx = talloc_new(module);
517 struct ldb_result *res;
519 res = talloc_zero(tmp_ctx, struct ldb_result);
520 if (!res) {
521 talloc_free(tmp_ctx);
522 return ldb_oom(ldb_module_get_ctx(module));
525 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
526 olddn,
527 newdn,
528 NULL,
529 res,
530 ldb_modify_default_callback,
531 parent);
532 LDB_REQ_SET_LOCATION(req);
533 if (ret != LDB_SUCCESS) {
534 talloc_free(tmp_ctx);
535 return ret;
538 ret = dsdb_request_add_controls(req, dsdb_flags);
539 if (ret != LDB_SUCCESS) {
540 talloc_free(tmp_ctx);
541 return ret;
544 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
545 ldb_req_mark_trusted(req);
548 /* Run the new request */
549 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
550 ret = ldb_next_request(module, req);
551 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
552 ret = ldb_request(ldb_module_get_ctx(module), req);
553 } else {
554 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
555 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
556 ret = ops->rename(module, req);
558 if (ret == LDB_SUCCESS) {
559 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
562 talloc_free(tmp_ctx);
563 return ret;
567 a ldb_add request operating on modules below the
568 current module
570 int dsdb_module_add(struct ldb_module *module,
571 const struct ldb_message *message,
572 uint32_t dsdb_flags,
573 struct ldb_request *parent)
575 struct ldb_request *req;
576 int ret;
577 struct ldb_context *ldb = ldb_module_get_ctx(module);
578 TALLOC_CTX *tmp_ctx = talloc_new(module);
579 struct ldb_result *res;
581 res = talloc_zero(tmp_ctx, struct ldb_result);
582 if (!res) {
583 talloc_free(tmp_ctx);
584 return ldb_oom(ldb_module_get_ctx(module));
587 ret = ldb_build_add_req(&req, ldb, tmp_ctx,
588 message,
589 NULL,
590 res,
591 ldb_modify_default_callback,
592 parent);
593 LDB_REQ_SET_LOCATION(req);
594 if (ret != LDB_SUCCESS) {
595 talloc_free(tmp_ctx);
596 return ret;
599 ret = dsdb_request_add_controls(req, dsdb_flags);
600 if (ret != LDB_SUCCESS) {
601 talloc_free(tmp_ctx);
602 return ret;
605 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
606 ldb_req_mark_trusted(req);
609 /* Run the new request */
610 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
611 ret = ldb_next_request(module, req);
612 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
613 ret = ldb_request(ldb_module_get_ctx(module), req);
614 } else {
615 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
616 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
617 ret = ops->add(module, req);
619 if (ret == LDB_SUCCESS) {
620 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
623 talloc_free(tmp_ctx);
624 return ret;
628 a ldb_delete request operating on modules below the
629 current module
631 int dsdb_module_del(struct ldb_module *module,
632 struct ldb_dn *dn,
633 uint32_t dsdb_flags,
634 struct ldb_request *parent)
636 struct ldb_request *req;
637 int ret;
638 struct ldb_context *ldb = ldb_module_get_ctx(module);
639 TALLOC_CTX *tmp_ctx = talloc_new(module);
640 struct ldb_result *res;
642 res = talloc_zero(tmp_ctx, struct ldb_result);
643 if (!res) {
644 talloc_free(tmp_ctx);
645 return ldb_oom(ldb);
648 ret = ldb_build_del_req(&req, ldb, tmp_ctx,
650 NULL,
651 res,
652 ldb_modify_default_callback,
653 parent);
654 LDB_REQ_SET_LOCATION(req);
655 if (ret != LDB_SUCCESS) {
656 talloc_free(tmp_ctx);
657 return ret;
660 ret = dsdb_request_add_controls(req, dsdb_flags);
661 if (ret != LDB_SUCCESS) {
662 talloc_free(tmp_ctx);
663 return ret;
666 if (dsdb_flags & DSDB_FLAG_TRUSTED) {
667 ldb_req_mark_trusted(req);
670 /* Run the new request */
671 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
672 ret = ldb_next_request(module, req);
673 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
674 ret = ldb_request(ldb_module_get_ctx(module), req);
675 } else {
676 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
677 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
678 ret = ops->del(module, req);
680 if (ret == LDB_SUCCESS) {
681 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
684 talloc_free(tmp_ctx);
685 return ret;
689 check if a single valued link has multiple non-deleted values
691 This is needed when we will be using the RELAX control to stop
692 ldb_tdb from checking single valued links
694 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
695 const struct ldb_message_element *el)
697 bool found_active = false;
698 unsigned int i;
700 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
701 el->num_values < 2) {
702 return LDB_SUCCESS;
705 for (i=0; i<el->num_values; i++) {
706 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
707 if (found_active) {
708 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
710 found_active = true;
714 return LDB_SUCCESS;
718 int dsdb_check_samba_compatible_feature(struct ldb_module *module,
719 const char *feature,
720 bool *found)
722 struct ldb_context *ldb = ldb_module_get_ctx(module);
723 struct ldb_result *res;
724 static const char * const samba_dsdb_attrs[] = {
725 SAMBA_COMPATIBLE_FEATURES_ATTR,
726 NULL
728 int ret;
729 struct ldb_dn *samba_dsdb_dn = NULL;
730 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
731 if (tmp_ctx == NULL) {
732 *found = false;
733 return ldb_oom(ldb);
735 *found = false;
737 samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
738 if (samba_dsdb_dn == NULL) {
739 TALLOC_FREE(tmp_ctx);
740 return ldb_oom(ldb);
743 ret = dsdb_module_search_dn(module,
744 tmp_ctx,
745 &res,
746 samba_dsdb_dn,
747 samba_dsdb_attrs,
748 DSDB_FLAG_NEXT_MODULE,
749 NULL);
750 if (ret == LDB_SUCCESS) {
751 *found = ldb_msg_check_string_attribute(
752 res->msgs[0],
753 SAMBA_COMPATIBLE_FEATURES_ATTR,
754 feature);
755 } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
756 /* it is not an error not to find it */
757 ret = LDB_SUCCESS;
759 TALLOC_FREE(tmp_ctx);
760 return ret;
765 check if an optional feature is enabled on our own NTDS DN
767 Note that features can be marked as enabled in more than one
768 place. For example, the recyclebin feature is marked as enabled both
769 on the CN=Partitions,CN=Configuration object and on the NTDS DN of
770 each DC in the forest. It seems likely that it is the job of the KCC
771 to propagate between the two
773 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
775 TALLOC_CTX *tmp_ctx;
776 struct ldb_context *ldb = ldb_module_get_ctx(module);
777 struct ldb_result *res;
778 struct ldb_dn *search_dn;
779 struct GUID search_guid;
780 static const char * const attrs[] = {"msDS-EnabledFeature", NULL};
781 int ret;
782 unsigned int i;
783 struct ldb_message_element *el;
784 struct ldb_dn *feature_dn;
786 tmp_ctx = talloc_new(ldb);
788 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
789 if (feature_dn == NULL) {
790 talloc_free(tmp_ctx);
791 return ldb_operr(ldb_module_get_ctx(module));
794 *feature_enabled = false;
796 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
797 if (ret != LDB_SUCCESS) {
798 ldb_asprintf_errstring(ldb,
799 "Could not find the feature object - dn: %s\n",
800 ldb_dn_get_linearized(feature_dn));
801 talloc_free(tmp_ctx);
802 return LDB_ERR_NO_SUCH_OBJECT;
804 if (res->msgs[0]->num_elements > 0) {
805 static const char * const attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
807 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
809 for (i=0; i<el->num_values; i++) {
810 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
812 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
813 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
814 if (ret != LDB_SUCCESS) {
815 ldb_asprintf_errstring(ldb,
816 "Could no find object dn: %s\n",
817 ldb_dn_get_linearized(search_dn));
818 talloc_free(tmp_ctx);
819 return LDB_ERR_OPERATIONS_ERROR;
822 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
824 if (GUID_equal(&search_guid, &op_feature_guid)) {
825 *feature_enabled = true;
826 break;
830 talloc_free(tmp_ctx);
831 return LDB_SUCCESS;
835 find the NTDS GUID from a computers DN record
837 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
838 TALLOC_CTX *mem_ctx,
839 struct ldb_dn *computer_dn,
840 struct GUID *ntds_guid,
841 struct ldb_request *parent)
843 int ret;
844 struct ldb_dn *dn;
846 *ntds_guid = GUID_zero();
848 ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
849 "serverReferenceBL", &dn, parent);
850 if (ret != LDB_SUCCESS) {
851 return ret;
854 if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
855 talloc_free(dn);
856 return LDB_ERR_OPERATIONS_ERROR;
859 ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
860 talloc_free(dn);
861 return ret;
865 find a 'reference' DN that points at another object
866 (eg. serverReference, rIDManagerReference etc)
868 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
869 const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
871 const char *attrs[2];
872 struct ldb_result *res;
873 int ret;
875 attrs[0] = attribute;
876 attrs[1] = NULL;
878 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
879 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
880 if (ret != LDB_SUCCESS) {
881 return ret;
884 *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
885 mem_ctx, res->msgs[0], attribute);
886 if (!*dn) {
887 ldb_reset_err_string(ldb_module_get_ctx(module));
888 talloc_free(res);
889 return LDB_ERR_NO_SUCH_ATTRIBUTE;
892 talloc_free(res);
893 return LDB_SUCCESS;
897 find the RID Manager$ DN via the rIDManagerReference attribute in the
898 base DN
900 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
901 struct ldb_request *parent)
903 return dsdb_module_reference_dn(module, mem_ctx,
904 ldb_get_default_basedn(ldb_module_get_ctx(module)),
905 "rIDManagerReference", dn, parent);
909 used to chain to the callers callback
911 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
913 struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
915 if (!ares) {
916 return ldb_module_done(up_req, NULL, NULL,
917 LDB_ERR_OPERATIONS_ERROR);
920 if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
921 return ldb_module_done(up_req, ares->controls,
922 ares->response, ares->error);
925 /* Otherwise pass on the callback */
926 switch (ares->type) {
927 case LDB_REPLY_ENTRY:
928 return ldb_module_send_entry(up_req, ares->message,
929 ares->controls);
931 case LDB_REPLY_REFERRAL:
932 return ldb_module_send_referral(up_req,
933 ares->referral);
934 default:
935 /* Can't happen */
936 return LDB_ERR_OPERATIONS_ERROR;
941 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
942 object for a partition
944 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
945 uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
947 struct ldb_context *ldb = ldb_module_get_ctx(module);
948 struct ldb_request *req;
949 int ret;
950 TALLOC_CTX *tmp_ctx = talloc_new(module);
951 struct dsdb_control_current_partition *p_ctrl;
952 struct ldb_result *res;
954 res = talloc_zero(tmp_ctx, struct ldb_result);
955 if (!res) {
956 talloc_free(tmp_ctx);
957 return ldb_module_oom(module);
960 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
961 ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
962 LDB_SCOPE_BASE,
963 NULL, NULL,
964 NULL,
965 res, ldb_search_default_callback,
966 parent);
967 LDB_REQ_SET_LOCATION(req);
968 if (ret != LDB_SUCCESS) {
969 talloc_free(tmp_ctx);
970 return ret;
973 p_ctrl = talloc(req, struct dsdb_control_current_partition);
974 if (p_ctrl == NULL) {
975 talloc_free(tmp_ctx);
976 return ldb_module_oom(module);
978 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
979 p_ctrl->dn = dn;
982 ret = ldb_request_add_control(req,
983 DSDB_CONTROL_CURRENT_PARTITION_OID,
984 false, p_ctrl);
985 if (ret != LDB_SUCCESS) {
986 talloc_free(tmp_ctx);
987 return ret;
990 /* Run the new request */
991 ret = ldb_next_request(module, req);
993 if (ret == LDB_SUCCESS) {
994 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
997 if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
998 /* it hasn't been created yet, which means
999 an implicit value of zero */
1000 *uSN = 0;
1001 talloc_free(tmp_ctx);
1002 ldb_reset_err_string(ldb);
1003 return LDB_SUCCESS;
1006 if (ret != LDB_SUCCESS) {
1007 talloc_free(tmp_ctx);
1008 return ret;
1011 if (res->count != 1) {
1012 *uSN = 0;
1013 if (urgent_uSN) {
1014 *urgent_uSN = 0;
1016 } else {
1017 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
1018 if (urgent_uSN) {
1019 *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
1023 talloc_free(tmp_ctx);
1025 return LDB_SUCCESS;
1029 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
1030 partition
1032 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
1033 uint64_t uSN, uint64_t urgent_uSN,
1034 struct ldb_request *parent)
1036 struct ldb_context *ldb = ldb_module_get_ctx(module);
1037 struct ldb_request *req;
1038 struct ldb_message *msg;
1039 struct dsdb_control_current_partition *p_ctrl;
1040 int ret;
1041 struct ldb_result *res;
1043 msg = ldb_msg_new(module);
1044 if (msg == NULL) {
1045 return ldb_module_oom(module);
1048 msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
1049 if (msg->dn == NULL) {
1050 talloc_free(msg);
1051 return ldb_operr(ldb_module_get_ctx(module));
1054 res = talloc_zero(msg, struct ldb_result);
1055 if (!res) {
1056 talloc_free(msg);
1057 return ldb_module_oom(module);
1060 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
1061 if (ret != LDB_SUCCESS) {
1062 talloc_free(msg);
1063 return ret;
1065 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1067 /* urgent_uSN is optional so may not be stored */
1068 if (urgent_uSN) {
1069 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
1070 urgent_uSN);
1071 if (ret != LDB_SUCCESS) {
1072 talloc_free(msg);
1073 return ret;
1075 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1079 p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1080 if (p_ctrl == NULL) {
1081 talloc_free(msg);
1082 return ldb_oom(ldb);
1084 p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1085 p_ctrl->dn = dn;
1086 ret = ldb_build_mod_req(&req, ldb, msg,
1087 msg,
1088 NULL,
1089 res,
1090 ldb_modify_default_callback,
1091 parent);
1092 LDB_REQ_SET_LOCATION(req);
1093 again:
1094 if (ret != LDB_SUCCESS) {
1095 talloc_free(msg);
1096 return ret;
1099 ret = ldb_request_add_control(req,
1100 DSDB_CONTROL_CURRENT_PARTITION_OID,
1101 false, p_ctrl);
1102 if (ret != LDB_SUCCESS) {
1103 talloc_free(msg);
1104 return ret;
1107 /* Run the new request */
1108 ret = ldb_next_request(module, req);
1110 if (ret == LDB_SUCCESS) {
1111 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1113 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1114 ret = ldb_build_add_req(&req, ldb, msg,
1115 msg,
1116 NULL,
1117 res,
1118 ldb_modify_default_callback,
1119 parent);
1120 LDB_REQ_SET_LOCATION(req);
1121 goto again;
1124 talloc_free(msg);
1126 return ret;
1129 bool dsdb_module_am_system(struct ldb_module *module)
1131 struct ldb_context *ldb = ldb_module_get_ctx(module);
1132 struct auth_session_info *session_info
1133 = talloc_get_type(
1134 ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1135 struct auth_session_info);
1136 return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1139 bool dsdb_module_am_administrator(struct ldb_module *module)
1141 struct ldb_context *ldb = ldb_module_get_ctx(module);
1142 struct auth_session_info *session_info
1143 = talloc_get_type(
1144 ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1145 struct auth_session_info);
1146 return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1150 check if the recyclebin is enabled
1152 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1154 struct ldb_context *ldb = ldb_module_get_ctx(module);
1155 struct GUID recyclebin_guid;
1156 int ret;
1158 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1160 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1161 if (ret != LDB_SUCCESS) {
1162 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1163 return ret;
1166 return LDB_SUCCESS;
1169 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1170 struct ldb_message *msg,
1171 const char *attr,
1172 const int32_t *old_val,
1173 const int32_t *new_val)
1175 struct ldb_message_element *el;
1176 int ret;
1177 char *vstring;
1179 if (old_val) {
1180 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1181 if (ret != LDB_SUCCESS) {
1182 return ret;
1184 el->num_values = 1;
1185 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1186 if (!el->values) {
1187 return ldb_module_oom(module);
1189 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1190 if (!vstring) {
1191 return ldb_module_oom(module);
1193 *el->values = data_blob_string_const(vstring);
1196 if (new_val) {
1197 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1198 if (ret != LDB_SUCCESS) {
1199 return ret;
1201 el->num_values = 1;
1202 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1203 if (!el->values) {
1204 return ldb_module_oom(module);
1206 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1207 if (!vstring) {
1208 return ldb_module_oom(module);
1210 *el->values = data_blob_string_const(vstring);
1213 return LDB_SUCCESS;
1216 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1217 struct ldb_message *msg,
1218 const char *attr,
1219 const uint32_t *old_val,
1220 const uint32_t *new_val)
1222 return dsdb_msg_constrainted_update_int32(module, msg, attr,
1223 (const int32_t *)old_val,
1224 (const int32_t *)new_val);
1227 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1228 struct ldb_message *msg,
1229 const char *attr,
1230 const int64_t *old_val,
1231 const int64_t *new_val)
1233 struct ldb_message_element *el;
1234 int ret;
1235 char *vstring;
1237 if (old_val) {
1238 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1239 if (ret != LDB_SUCCESS) {
1240 return ret;
1242 el->num_values = 1;
1243 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1244 if (!el->values) {
1245 return ldb_module_oom(module);
1247 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1248 if (!vstring) {
1249 return ldb_module_oom(module);
1251 *el->values = data_blob_string_const(vstring);
1254 if (new_val) {
1255 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1256 if (ret != LDB_SUCCESS) {
1257 return ret;
1259 el->num_values = 1;
1260 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1261 if (!el->values) {
1262 return ldb_module_oom(module);
1264 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1265 if (!vstring) {
1266 return ldb_module_oom(module);
1268 *el->values = data_blob_string_const(vstring);
1271 return LDB_SUCCESS;
1274 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1275 struct ldb_message *msg,
1276 const char *attr,
1277 const uint64_t *old_val,
1278 const uint64_t *new_val)
1280 return dsdb_msg_constrainted_update_int64(module, msg, attr,
1281 (const int64_t *)old_val,
1282 (const int64_t *)new_val);
1286 update an int32 attribute safely via a constrained delete/add
1288 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1289 struct ldb_dn *dn,
1290 const char *attr,
1291 const int32_t *old_val,
1292 const int32_t *new_val,
1293 struct ldb_request *parent)
1295 struct ldb_message *msg;
1296 int ret;
1298 msg = ldb_msg_new(module);
1299 if (msg == NULL) {
1300 return ldb_module_oom(module);
1302 msg->dn = dn;
1304 ret = dsdb_msg_constrainted_update_int32(module,
1305 msg, attr,
1306 old_val,
1307 new_val);
1308 if (ret != LDB_SUCCESS) {
1309 talloc_free(msg);
1310 return ret;
1313 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1314 talloc_free(msg);
1315 return ret;
1318 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1319 struct ldb_dn *dn,
1320 const char *attr,
1321 const uint32_t *old_val,
1322 const uint32_t *new_val,
1323 struct ldb_request *parent)
1325 return dsdb_module_constrainted_update_int32(module, dn, attr,
1326 (const int32_t *)old_val,
1327 (const int32_t *)new_val, parent);
1331 update an int64 attribute safely via a constrained delete/add
1333 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1334 struct ldb_dn *dn,
1335 const char *attr,
1336 const int64_t *old_val,
1337 const int64_t *new_val,
1338 struct ldb_request *parent)
1340 struct ldb_message *msg;
1341 int ret;
1343 msg = ldb_msg_new(module);
1344 if (msg == NULL) {
1345 return ldb_module_oom(module);
1347 msg->dn = dn;
1349 ret = dsdb_msg_constrainted_update_int64(module,
1350 msg, attr,
1351 old_val,
1352 new_val);
1353 if (ret != LDB_SUCCESS) {
1354 talloc_free(msg);
1355 return ret;
1358 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1359 talloc_free(msg);
1360 return ret;
1363 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1364 struct ldb_dn *dn,
1365 const char *attr,
1366 const uint64_t *old_val,
1367 const uint64_t *new_val,
1368 struct ldb_request *parent)
1370 return dsdb_module_constrainted_update_int64(module, dn, attr,
1371 (const int64_t *)old_val,
1372 (const int64_t *)new_val,
1373 parent);
1377 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1378 TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1380 int ret;
1381 struct ldb_dn *new_dn;
1382 struct ldb_context *ldb = ldb_module_get_ctx(module);
1383 static const char * const attrs[] = { "dSHeuristics", NULL };
1384 struct ldb_result *res;
1386 new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1387 if (!ldb_dn_add_child_fmt(new_dn,
1388 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1389 talloc_free(new_dn);
1390 return NULL;
1392 ret = dsdb_module_search_dn(module, mem_ctx, &res,
1393 new_dn,
1394 attrs,
1395 DSDB_FLAG_NEXT_MODULE,
1396 parent);
1397 if (ret == LDB_SUCCESS && res->count == 1) {
1398 talloc_free(new_dn);
1399 return ldb_msg_find_ldb_val(res->msgs[0],
1400 "dSHeuristics");
1402 talloc_free(new_dn);
1403 return NULL;
1406 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1408 TALLOC_CTX *tmp_ctx = talloc_new(module);
1409 bool result;
1410 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1411 tmp_ctx, parent);
1412 if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1413 result = true;
1414 } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1415 result = false;
1416 } else {
1417 result = true;
1420 talloc_free(tmp_ctx);
1421 return result;
1424 bool dsdb_user_password_support(struct ldb_module *module,
1425 TALLOC_CTX *mem_ctx,
1426 struct ldb_request *parent)
1428 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1429 bool result;
1430 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1431 tmp_ctx,
1432 parent);
1433 if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1434 result = false;
1435 } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1436 (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1437 result = false;
1438 } else {
1439 result = true;
1442 talloc_free(tmp_ctx);
1443 return result;
1446 bool dsdb_do_list_object(struct ldb_module *module,
1447 TALLOC_CTX *mem_ctx,
1448 struct ldb_request *parent)
1450 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1451 bool result;
1452 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1453 tmp_ctx,
1454 parent);
1455 if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
1456 result = false;
1457 } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
1458 result = true;
1459 } else {
1460 result = false;
1463 talloc_free(tmp_ctx);
1464 return result;
1467 bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
1468 TALLOC_CTX *mem_ctx,
1469 struct ldb_request *parent)
1471 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1472 bool result = false;
1473 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1474 tmp_ctx,
1475 parent);
1476 if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) {
1477 uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1];
1478 if (val != '0' && val != '2') {
1479 result = true;
1483 talloc_free(tmp_ctx);
1484 return result;
1487 bool dsdb_block_owner_implicit_rights(struct ldb_module *module,
1488 TALLOC_CTX *mem_ctx,
1489 struct ldb_request *parent)
1491 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1492 bool result = false;
1493 const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1494 tmp_ctx,
1495 parent);
1496 if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) {
1497 uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1];
1498 if (val != '0' && val != '2') {
1499 result = true;
1503 talloc_free(tmp_ctx);
1504 return result;
1508 show the chain of requests, useful for debugging async requests
1510 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1512 char *s = ldb_module_call_chain(req, req);
1513 DEBUG(level, ("%s\n", s));
1514 talloc_free(s);
1518 * Get all the values that *might* be added by an ldb message, as a composite
1519 * ldb element.
1521 * This is useful when we need to check all the possible values against some
1522 * criteria.
1524 * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES,
1525 * the returned element might contain more values than would actually end up
1526 * in the database if the message was run to its conclusion.
1528 * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is
1529 * returned.
1531 * The returned element might not be new, and should not be modified or freed
1532 * before the message is finished.
1535 int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
1536 const struct ldb_message *msg,
1537 const char *attr_name,
1538 struct ldb_message_element **el,
1539 enum ldb_request_type operation)
1541 unsigned int i;
1542 unsigned int el_count = 0;
1543 unsigned int val_count = 0;
1544 struct ldb_val *v = NULL;
1545 struct ldb_message_element *_el = NULL;
1546 *el = NULL;
1548 if (operation != LDB_ADD && operation != LDB_MODIFY) {
1549 DBG_ERR("inapplicable operation type: %d\n", operation);
1550 return LDB_ERR_OPERATIONS_ERROR;
1553 /* count the adding or replacing elements */
1554 for (i = 0; i < msg->num_elements; i++) {
1555 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1556 unsigned int tmp;
1557 if ((operation == LDB_MODIFY) &&
1558 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1559 == LDB_FLAG_MOD_DELETE)) {
1560 continue;
1562 el_count++;
1563 tmp = val_count + msg->elements[i].num_values;
1564 if (unlikely(tmp < val_count)) {
1565 DBG_ERR("too many values for one element!\n");
1566 return LDB_ERR_OPERATIONS_ERROR;
1568 val_count = tmp;
1571 if (el_count == 0) {
1572 /* nothing to see here */
1573 return LDB_SUCCESS;
1576 if (el_count == 1 || val_count == 0) {
1578 * There is one effective element, which we can return as-is,
1579 * OR there are only elements with zero values -- any of which
1580 * will do.
1582 for (i = 0; i < msg->num_elements; i++) {
1583 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1584 if ((operation == LDB_MODIFY) &&
1585 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1586 == LDB_FLAG_MOD_DELETE)) {
1587 continue;
1589 *el = &msg->elements[i];
1590 return LDB_SUCCESS;
1595 _el = talloc_zero(mem_ctx, struct ldb_message_element);
1596 if (_el == NULL) {
1597 return LDB_ERR_OPERATIONS_ERROR;
1599 _el->name = attr_name;
1601 if (val_count == 0) {
1603 * Seems unlikely, but sometimes we might be adding zero
1604 * values in multiple separate elements. The talloc zero has
1605 * already set the expected values = NULL, num_values = 0.
1607 *el = _el;
1608 return LDB_SUCCESS;
1611 _el->values = talloc_array(_el, struct ldb_val, val_count);
1612 if (_el->values == NULL) {
1613 talloc_free(_el);
1614 return LDB_ERR_OPERATIONS_ERROR;
1616 _el->num_values = val_count;
1618 v = _el->values;
1620 for (i = 0; i < msg->num_elements; i++) {
1621 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1622 const struct ldb_message_element *tmp_el = &msg->elements[i];
1623 if ((operation == LDB_MODIFY) &&
1624 (LDB_FLAG_MOD_TYPE(tmp_el->flags)
1625 == LDB_FLAG_MOD_DELETE)) {
1626 continue;
1628 if (tmp_el->values == NULL || tmp_el->num_values == 0) {
1629 continue;
1631 memcpy(v,
1632 tmp_el->values,
1633 tmp_el->num_values * sizeof(*v));
1634 v += tmp_el->num_values;
1638 *el = _el;
1639 return LDB_SUCCESS;
1644 * Get the value of a single-valued attribute from an ADDed message. 'val' will only live as
1645 * long as 'msg' and 'original_val' do, and must not be freed.
1647 int dsdb_msg_add_get_single_value(const struct ldb_message *msg,
1648 const char *attr_name,
1649 const struct ldb_val **val)
1651 const struct ldb_message_element *el = NULL;
1654 * The ldb_msg_normalize() call in ldb_request() ensures that
1655 * there is at most one message element for each
1656 * attribute. Thus, we don't need a loop to deal with an
1657 * LDB_ADD.
1659 el = ldb_msg_find_element(msg, attr_name);
1660 if (el == NULL) {
1661 *val = NULL;
1662 return LDB_SUCCESS;
1664 if (el->num_values != 1) {
1665 return LDB_ERR_CONSTRAINT_VIOLATION;
1668 *val = &el->values[0];
1669 return LDB_SUCCESS;
1673 * Get the value of a single-valued attribute after processing a
1674 * message. 'operation' is either LDB_ADD or LDB_MODIFY. 'val' will only live as
1675 * long as 'msg' and 'original_val' do, and must not be freed.
1677 int dsdb_msg_get_single_value(const struct ldb_message *msg,
1678 const char *attr_name,
1679 const struct ldb_val *original_val,
1680 const struct ldb_val **val,
1681 enum ldb_request_type operation)
1683 unsigned idx;
1685 *val = NULL;
1687 if (operation == LDB_ADD) {
1688 if (original_val != NULL) {
1689 /* This is an error on the caller's part. */
1690 return LDB_ERR_CONSTRAINT_VIOLATION;
1692 return dsdb_msg_add_get_single_value(msg, attr_name, val);
1695 SMB_ASSERT(operation == LDB_MODIFY);
1697 *val = original_val;
1699 for (idx = 0; idx < msg->num_elements; ++idx) {
1700 const struct ldb_message_element *el = &msg->elements[idx];
1702 if (ldb_attr_cmp(el->name, attr_name) != 0) {
1703 continue;
1706 switch (el->flags & LDB_FLAG_MOD_MASK) {
1707 case LDB_FLAG_MOD_ADD:
1708 if (el->num_values != 1) {
1709 return LDB_ERR_CONSTRAINT_VIOLATION;
1711 if (*val != NULL) {
1712 return LDB_ERR_CONSTRAINT_VIOLATION;
1715 *val = &el->values[0];
1717 break;
1719 case LDB_FLAG_MOD_REPLACE:
1720 if (el->num_values > 1) {
1721 return LDB_ERR_CONSTRAINT_VIOLATION;
1724 *val = el->num_values ? &el->values[0] : NULL;
1726 break;
1728 case LDB_FLAG_MOD_DELETE:
1729 if (el->num_values > 1) {
1730 return LDB_ERR_CONSTRAINT_VIOLATION;
1734 * If a value was specified for the delete, we don't
1735 * bother checking it matches the value we currently
1736 * have. Any mismatch will be caught later (e.g. in
1737 * ldb_kv_modify_internal).
1740 *val = NULL;
1742 break;
1746 return LDB_SUCCESS;
1750 * This function determines the (last) structural or 88 object class of a passed
1751 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1752 * Without schema this does not work and hence NULL is returned.
1754 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1755 const struct ldb_message_element *element)
1757 const struct dsdb_class *last_class;
1759 if (schema == NULL) {
1760 return NULL;
1763 if (element->num_values == 0) {
1764 return NULL;
1767 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1768 &element->values[element->num_values-1]);
1769 if (last_class == NULL) {
1770 return NULL;
1772 if (last_class->objectClassCategory > 1) {
1773 return NULL;
1776 return last_class;
1779 const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1780 const struct ldb_message *msg)
1782 struct ldb_message_element *oc_el;
1784 oc_el = ldb_msg_find_element(msg, "objectClass");
1785 if (!oc_el) {
1786 return NULL;
1789 return dsdb_get_last_structural_class(schema, oc_el);
1793 Get the parent class of an objectclass, or NULL if none exists.
1795 const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
1796 const struct dsdb_class *objectclass)
1798 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
1799 return NULL;
1802 if (objectclass->subClassOf == NULL) {
1803 return NULL;
1806 return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
1810 Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
1811 two objectclasses must originate from the same schema, to allow for
1812 pointer-based identity comparison.
1814 bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
1815 const struct dsdb_class *struct_objectclass,
1816 const struct dsdb_class *other_objectclass)
1818 while (struct_objectclass != NULL) {
1819 /* Pointer comparison can be used due to the same schema str. */
1820 if (struct_objectclass == other_objectclass) {
1821 return true;
1824 struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
1827 return false;
1830 /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1831 cn=Administrator,cn=users,dc=samba,dc=example,dc=com becomes
1832 CN=Administrator,CN=users,DC=samba,DC=example,DC=com
1834 int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1836 int i, ret;
1837 char *upper_rdn_attr;
1839 for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1840 /* We need the attribute name in upper case */
1841 upper_rdn_attr = strupper_talloc(dn,
1842 ldb_dn_get_component_name(dn, i));
1843 if (!upper_rdn_attr) {
1844 return ldb_oom(ldb);
1846 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1847 *ldb_dn_get_component_val(dn, i));
1848 talloc_free(upper_rdn_attr);
1849 if (ret != LDB_SUCCESS) {
1850 return ret;
1853 return LDB_SUCCESS;
1857 * Make most specific objectCategory for the objectClass of passed object
1858 * NOTE: In this implementation we count that it is called on already
1859 * verified objectClass attribute value. See objectclass.c thorough
1860 * implementation for all the magic that involves
1862 * @param ldb ldb context
1863 * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1864 * Hence leave the responsibility to the caller.
1865 * @param obj AD object to determine objectCategory for
1866 * @param mem_ctx Memory context - usually it is obj actually
1867 * @param pobjectcategory location to store found objectCategory
1869 * @return LDB_SUCCESS or error including out of memory error
1871 int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1872 const struct ldb_message *obj,
1873 TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1875 const struct dsdb_class *objectclass;
1876 struct ldb_message_element *objectclass_element;
1877 struct dsdb_extended_dn_store_format *dn_format;
1879 objectclass_element = ldb_msg_find_element(obj, "objectClass");
1880 if (!objectclass_element) {
1881 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1882 ldb_dn_get_linearized(obj->dn));
1883 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1885 if (objectclass_element->num_values == 0) {
1886 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1887 ldb_dn_get_linearized(obj->dn));
1888 return LDB_ERR_CONSTRAINT_VIOLATION;
1892 * Get the new top-most structural object class and check for
1893 * unrelated structural classes
1895 objectclass = dsdb_get_last_structural_class(schema,
1896 objectclass_element);
1897 if (objectclass == NULL) {
1898 ldb_asprintf_errstring(ldb,
1899 "Failed to find a structural class for %s",
1900 ldb_dn_get_linearized(obj->dn));
1901 return LDB_ERR_UNWILLING_TO_PERFORM;
1904 dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1905 struct dsdb_extended_dn_store_format);
1906 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1907 /* Strip off extended components */
1908 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1909 objectclass->defaultObjectCategory);
1910 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1911 talloc_free(dn);
1912 } else {
1913 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1916 if (*pobjectcategory == NULL) {
1917 return ldb_oom(ldb);
1920 return LDB_SUCCESS;