2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 2009
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7 Copyright (C) Matthieu Patou <mat@matws.net> 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "ldb_module.h"
26 #include "librpc/ndr/libndr.h"
27 #include "dsdb/samdb/ldb_modules/util.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "dsdb/common/util.h"
30 #include "libcli/security/security.h"
35 search for attrs on one DN, in the modules below
37 int dsdb_module_search_dn(struct ldb_module
*module
,
39 struct ldb_result
**_res
,
40 struct ldb_dn
*basedn
,
41 const char * const *attrs
,
43 struct ldb_request
*parent
)
46 struct ldb_request
*req
;
48 struct ldb_result
*res
;
50 tmp_ctx
= talloc_new(mem_ctx
);
52 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
55 return ldb_oom(ldb_module_get_ctx(module
));
58 ret
= ldb_build_search_req(&req
, ldb_module_get_ctx(module
), tmp_ctx
,
65 ldb_search_default_callback
,
67 LDB_REQ_SET_LOCATION(req
);
68 if (ret
!= LDB_SUCCESS
) {
73 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
74 if (ret
!= LDB_SUCCESS
) {
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
);
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
) {
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
);
109 *_res
= talloc_steal(mem_ctx
, res
);
111 talloc_free(tmp_ctx
);
115 int dsdb_module_search_tree(struct ldb_module
*module
,
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
,
123 struct ldb_request
*parent
)
126 struct ldb_request
*req
;
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
);
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
,
148 ldb_search_default_callback
,
150 LDB_REQ_SET_LOCATION(req
);
151 if (ret
!= LDB_SUCCESS
) {
152 talloc_free(tmp_ctx
);
156 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
157 if (ret
!= LDB_SUCCESS
) {
158 talloc_free(tmp_ctx
);
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
);
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
;
192 if (ret
== LDB_SUCCESS
) {
193 *_res
= talloc_steal(mem_ctx
, res
);
195 talloc_free(tmp_ctx
);
200 search for attrs in the modules below
202 int dsdb_module_search(struct ldb_module
*module
,
204 struct ldb_result
**_res
,
205 struct ldb_dn
*basedn
, enum ldb_scope scope
,
206 const char * const *attrs
,
208 struct ldb_request
*parent
,
209 const char *format
, ...) _PRINTF_ATTRIBUTE(9, 10)
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
);
223 va_start(ap
, format
);
224 expression
= talloc_vasprintf(tmp_ctx
, format
, ap
);
228 talloc_free(tmp_ctx
);
229 return ldb_oom(ldb_module_get_ctx(module
));
235 tree
= ldb_parse_tree(tmp_ctx
, expression
);
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
,
253 talloc_free(tmp_ctx
);
258 find an object given a GUID. This searches across all partitions
260 int dsdb_module_obj_by_guid(struct ldb_module
*module
,
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
);
271 ret
= dsdb_module_search(module
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
273 DSDB_FLAG_NEXT_MODULE
|
274 DSDB_SEARCH_SHOW_RECYCLED
|
275 DSDB_SEARCH_SEARCH_ALL_PARTITIONS
|
276 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
,
278 "objectGUID=%s", GUID_string(tmp_ctx
, guid
));
279 if (ret
!= LDB_SUCCESS
) {
280 talloc_free(tmp_ctx
);
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
);
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
);
312 ret
= dsdb_module_obj_by_guid(module
,
318 if (ret
!= LDB_SUCCESS
) {
319 talloc_free(tmp_ctx
);
323 *dn
= talloc_steal(mem_ctx
, msg
->dn
);
325 talloc_free(tmp_ctx
);
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
);
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
,
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
);
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
);
365 a ldb_extended request operating on modules below the
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
,
373 struct ldb_result
**_res
,
374 const char* oid
, void* data
,
376 struct ldb_request
*parent
)
378 struct ldb_request
*req
;
380 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
381 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
382 struct ldb_result
*res
;
388 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
390 talloc_free(tmp_ctx
);
391 return ldb_oom(ldb_module_get_ctx(module
));
394 ret
= ldb_build_extended_req(&req
, ldb
,
399 res
, ldb_extended_default_callback
,
402 LDB_REQ_SET_LOCATION(req
);
403 if (ret
!= LDB_SUCCESS
) {
404 talloc_free(tmp_ctx
);
408 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
409 if (ret
!= LDB_SUCCESS
) {
410 talloc_free(tmp_ctx
);
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
);
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
);
442 a ldb_modify request operating on modules below the
445 int dsdb_module_modify(struct ldb_module
*module
,
446 const struct ldb_message
*message
,
448 struct ldb_request
*parent
)
450 struct ldb_request
*mod_req
;
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
);
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
,
466 ldb_modify_default_callback
,
468 LDB_REQ_SET_LOCATION(mod_req
);
469 if (ret
!= LDB_SUCCESS
) {
470 talloc_free(tmp_ctx
);
474 ret
= dsdb_request_add_controls(mod_req
, dsdb_flags
);
475 if (ret
!= LDB_SUCCESS
) {
476 talloc_free(tmp_ctx
);
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
);
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
);
505 a ldb_rename request operating on modules below the
508 int dsdb_module_rename(struct ldb_module
*module
,
509 struct ldb_dn
*olddn
, struct ldb_dn
*newdn
,
511 struct ldb_request
*parent
)
513 struct ldb_request
*req
;
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
);
521 talloc_free(tmp_ctx
);
522 return ldb_oom(ldb_module_get_ctx(module
));
525 ret
= ldb_build_rename_req(&req
, ldb
, tmp_ctx
,
530 ldb_modify_default_callback
,
532 LDB_REQ_SET_LOCATION(req
);
533 if (ret
!= LDB_SUCCESS
) {
534 talloc_free(tmp_ctx
);
538 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
539 if (ret
!= LDB_SUCCESS
) {
540 talloc_free(tmp_ctx
);
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
);
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
);
567 a ldb_add request operating on modules below the
570 int dsdb_module_add(struct ldb_module
*module
,
571 const struct ldb_message
*message
,
573 struct ldb_request
*parent
)
575 struct ldb_request
*req
;
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
);
583 talloc_free(tmp_ctx
);
584 return ldb_oom(ldb_module_get_ctx(module
));
587 ret
= ldb_build_add_req(&req
, ldb
, tmp_ctx
,
591 ldb_modify_default_callback
,
593 LDB_REQ_SET_LOCATION(req
);
594 if (ret
!= LDB_SUCCESS
) {
595 talloc_free(tmp_ctx
);
599 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
600 if (ret
!= LDB_SUCCESS
) {
601 talloc_free(tmp_ctx
);
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
);
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
);
628 a ldb_delete request operating on modules below the
631 int dsdb_module_del(struct ldb_module
*module
,
634 struct ldb_request
*parent
)
636 struct ldb_request
*req
;
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
);
644 talloc_free(tmp_ctx
);
648 ret
= ldb_build_del_req(&req
, ldb
, tmp_ctx
,
652 ldb_modify_default_callback
,
654 LDB_REQ_SET_LOCATION(req
);
655 if (ret
!= LDB_SUCCESS
) {
656 talloc_free(tmp_ctx
);
660 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
661 if (ret
!= LDB_SUCCESS
) {
662 talloc_free(tmp_ctx
);
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
);
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
);
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;
700 if (!(attr
->ldb_schema_attribute
->flags
& LDB_ATTR_FLAG_SINGLE_VALUE
) ||
701 el
->num_values
< 2) {
705 for (i
=0; i
<el
->num_values
; i
++) {
706 if (!dsdb_dn_is_deleted_val(&el
->values
[i
])) {
708 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
;
718 int dsdb_check_samba_compatible_feature(struct ldb_module
*module
,
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
,
729 struct ldb_dn
*samba_dsdb_dn
= NULL
;
730 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
731 if (tmp_ctx
== NULL
) {
737 samba_dsdb_dn
= ldb_dn_new(tmp_ctx
, ldb
, "@SAMBA_DSDB");
738 if (samba_dsdb_dn
== NULL
) {
739 TALLOC_FREE(tmp_ctx
);
743 ret
= dsdb_module_search_dn(module
,
748 DSDB_FLAG_NEXT_MODULE
,
750 if (ret
== LDB_SUCCESS
) {
751 *found
= ldb_msg_check_string_attribute(
753 SAMBA_COMPATIBLE_FEATURES_ATTR
,
755 } else if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
756 /* it is not an error not to find it */
759 TALLOC_FREE(tmp_ctx
);
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
)
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
};
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;
830 talloc_free(tmp_ctx
);
835 find the NTDS GUID from a computers DN record
837 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module
*module
,
839 struct ldb_dn
*computer_dn
,
840 struct GUID
*ntds_guid
,
841 struct ldb_request
*parent
)
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
) {
854 if (!ldb_dn_add_child_fmt(dn
, "CN=NTDS Settings")) {
856 return LDB_ERR_OPERATIONS_ERROR
;
859 ret
= dsdb_module_guid_by_dn(module
, dn
, ntds_guid
, parent
);
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
;
875 attrs
[0] = attribute
;
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
) {
884 *dn
= ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module
),
885 mem_ctx
, res
->msgs
[0], attribute
);
887 ldb_reset_err_string(ldb_module_get_ctx(module
));
889 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
897 find the RID Manager$ DN via the rIDManagerReference attribute in the
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
);
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
,
931 case LDB_REPLY_REFERRAL
:
932 return ldb_module_send_referral(up_req
,
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
;
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
);
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"),
965 res
, ldb_search_default_callback
,
967 LDB_REQ_SET_LOCATION(req
);
968 if (ret
!= LDB_SUCCESS
) {
969 talloc_free(tmp_ctx
);
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
;
982 ret
= ldb_request_add_control(req
,
983 DSDB_CONTROL_CURRENT_PARTITION_OID
,
985 if (ret
!= LDB_SUCCESS
) {
986 talloc_free(tmp_ctx
);
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 */
1001 talloc_free(tmp_ctx
);
1002 ldb_reset_err_string(ldb
);
1006 if (ret
!= LDB_SUCCESS
) {
1007 talloc_free(tmp_ctx
);
1011 if (res
->count
!= 1) {
1017 *uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNHighest", 0);
1019 *urgent_uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNUrgent", 0);
1023 talloc_free(tmp_ctx
);
1029 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
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
;
1041 struct ldb_result
*res
;
1043 msg
= ldb_msg_new(module
);
1045 return ldb_module_oom(module
);
1048 msg
->dn
= ldb_dn_new(msg
, ldb
, "@REPLCHANGED");
1049 if (msg
->dn
== NULL
) {
1051 return ldb_operr(ldb_module_get_ctx(module
));
1054 res
= talloc_zero(msg
, struct ldb_result
);
1057 return ldb_module_oom(module
);
1060 ret
= samdb_msg_add_uint64(ldb
, msg
, msg
, "uSNHighest", uSN
);
1061 if (ret
!= LDB_SUCCESS
) {
1065 msg
->elements
[0].flags
= LDB_FLAG_MOD_REPLACE
;
1067 /* urgent_uSN is optional so may not be stored */
1069 ret
= samdb_msg_add_uint64(ldb
, msg
, msg
, "uSNUrgent",
1071 if (ret
!= LDB_SUCCESS
) {
1075 msg
->elements
[1].flags
= LDB_FLAG_MOD_REPLACE
;
1079 p_ctrl
= talloc(msg
, struct dsdb_control_current_partition
);
1080 if (p_ctrl
== NULL
) {
1082 return ldb_oom(ldb
);
1084 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
1086 ret
= ldb_build_mod_req(&req
, ldb
, msg
,
1090 ldb_modify_default_callback
,
1092 LDB_REQ_SET_LOCATION(req
);
1094 if (ret
!= LDB_SUCCESS
) {
1099 ret
= ldb_request_add_control(req
,
1100 DSDB_CONTROL_CURRENT_PARTITION_OID
,
1102 if (ret
!= LDB_SUCCESS
) {
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
,
1118 ldb_modify_default_callback
,
1120 LDB_REQ_SET_LOCATION(req
);
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
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
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
;
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");
1169 int dsdb_msg_constrainted_update_int32(struct ldb_module
*module
,
1170 struct ldb_message
*msg
,
1172 const int32_t *old_val
,
1173 const int32_t *new_val
)
1175 struct ldb_message_element
*el
;
1180 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1181 if (ret
!= LDB_SUCCESS
) {
1185 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1187 return ldb_module_oom(module
);
1189 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*old_val
);
1191 return ldb_module_oom(module
);
1193 *el
->values
= data_blob_string_const(vstring
);
1197 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1198 if (ret
!= LDB_SUCCESS
) {
1202 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1204 return ldb_module_oom(module
);
1206 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*new_val
);
1208 return ldb_module_oom(module
);
1210 *el
->values
= data_blob_string_const(vstring
);
1216 int dsdb_msg_constrainted_update_uint32(struct ldb_module
*module
,
1217 struct ldb_message
*msg
,
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
,
1230 const int64_t *old_val
,
1231 const int64_t *new_val
)
1233 struct ldb_message_element
*el
;
1238 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1239 if (ret
!= LDB_SUCCESS
) {
1243 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1245 return ldb_module_oom(module
);
1247 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*old_val
);
1249 return ldb_module_oom(module
);
1251 *el
->values
= data_blob_string_const(vstring
);
1255 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1256 if (ret
!= LDB_SUCCESS
) {
1260 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1262 return ldb_module_oom(module
);
1264 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*new_val
);
1266 return ldb_module_oom(module
);
1268 *el
->values
= data_blob_string_const(vstring
);
1274 int dsdb_msg_constrainted_update_uint64(struct ldb_module
*module
,
1275 struct ldb_message
*msg
,
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
,
1291 const int32_t *old_val
,
1292 const int32_t *new_val
,
1293 struct ldb_request
*parent
)
1295 struct ldb_message
*msg
;
1298 msg
= ldb_msg_new(module
);
1300 return ldb_module_oom(module
);
1304 ret
= dsdb_msg_constrainted_update_int32(module
,
1308 if (ret
!= LDB_SUCCESS
) {
1313 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1318 int dsdb_module_constrainted_update_uint32(struct ldb_module
*module
,
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
,
1336 const int64_t *old_val
,
1337 const int64_t *new_val
,
1338 struct ldb_request
*parent
)
1340 struct ldb_message
*msg
;
1343 msg
= ldb_msg_new(module
);
1345 return ldb_module_oom(module
);
1349 ret
= dsdb_msg_constrainted_update_int64(module
,
1353 if (ret
!= LDB_SUCCESS
) {
1358 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1363 int dsdb_module_constrainted_update_uint64(struct ldb_module
*module
,
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
,
1377 const struct ldb_val
*dsdb_module_find_dsheuristics(struct ldb_module
*module
,
1378 TALLOC_CTX
*mem_ctx
, struct ldb_request
*parent
)
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
);
1392 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
,
1395 DSDB_FLAG_NEXT_MODULE
,
1397 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1398 talloc_free(new_dn
);
1399 return ldb_msg_find_ldb_val(res
->msgs
[0],
1402 talloc_free(new_dn
);
1406 bool dsdb_block_anonymous_ops(struct ldb_module
*module
, struct ldb_request
*parent
)
1408 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
1410 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1412 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_BLOCK_ANONYMOUS_OPS
) {
1414 } else if (hr_val
->data
[DS_HR_BLOCK_ANONYMOUS_OPS
-1] == '2') {
1420 talloc_free(tmp_ctx
);
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
);
1430 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1433 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_USER_PASSWORD_SUPPORT
) {
1435 } else if ((hr_val
->data
[DS_HR_USER_PASSWORD_SUPPORT
-1] == '2') ||
1436 (hr_val
->data
[DS_HR_USER_PASSWORD_SUPPORT
-1] == '0')) {
1442 talloc_free(tmp_ctx
);
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
);
1452 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1455 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_DOLISTOBJECT
) {
1457 } else if (hr_val
->data
[DS_HR_DOLISTOBJECT
-1] == '1') {
1463 talloc_free(tmp_ctx
);
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
,
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') {
1483 talloc_free(tmp_ctx
);
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
,
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') {
1503 talloc_free(tmp_ctx
);
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
));
1518 * Get all the values that *might* be added by an ldb message, as a composite
1521 * This is useful when we need to check all the possible values against some
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
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
)
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
;
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) {
1557 if ((operation
== LDB_MODIFY
) &&
1558 (LDB_FLAG_MOD_TYPE(msg
->elements
[i
].flags
)
1559 == LDB_FLAG_MOD_DELETE
)) {
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
;
1571 if (el_count
== 0) {
1572 /* nothing to see here */
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
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
)) {
1589 *el
= &msg
->elements
[i
];
1595 _el
= talloc_zero(mem_ctx
, struct ldb_message_element
);
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.
1611 _el
->values
= talloc_array(_el
, struct ldb_val
, val_count
);
1612 if (_el
->values
== NULL
) {
1614 return LDB_ERR_OPERATIONS_ERROR
;
1616 _el
->num_values
= val_count
;
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
)) {
1628 if (tmp_el
->values
== NULL
|| tmp_el
->num_values
== 0) {
1633 tmp_el
->num_values
* sizeof(*v
));
1634 v
+= tmp_el
->num_values
;
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
1659 el
= ldb_msg_find_element(msg
, attr_name
);
1664 if (el
->num_values
!= 1) {
1665 return LDB_ERR_CONSTRAINT_VIOLATION
;
1668 *val
= &el
->values
[0];
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
)
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) {
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
;
1712 return LDB_ERR_CONSTRAINT_VIOLATION
;
1715 *val
= &el
->values
[0];
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
;
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).
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
) {
1763 if (element
->num_values
== 0) {
1767 last_class
= dsdb_class_by_lDAPDisplayName_ldb_val(schema
,
1768 &element
->values
[element
->num_values
-1]);
1769 if (last_class
== NULL
) {
1772 if (last_class
->objectClassCategory
> 1) {
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");
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) {
1802 if (objectclass
->subClassOf
== 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
) {
1824 struct_objectclass
= dsdb_get_parent_class(schema
, struct_objectclass
);
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
)
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
) {
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
);
1913 *pobjectcategory
= talloc_strdup(mem_ctx
, objectclass
->defaultObjectCategory
);
1916 if (*pobjectcategory
== NULL
) {
1917 return ldb_oom(ldb
);