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"
33 search for attrs on one DN, in the modules below
35 int dsdb_module_search_dn(struct ldb_module
*module
,
37 struct ldb_result
**_res
,
38 struct ldb_dn
*basedn
,
39 const char * const *attrs
,
41 struct ldb_request
*parent
)
44 struct ldb_request
*req
;
46 struct ldb_result
*res
;
48 tmp_ctx
= talloc_new(mem_ctx
);
50 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
53 return ldb_oom(ldb_module_get_ctx(module
));
56 ret
= ldb_build_search_req(&req
, ldb_module_get_ctx(module
), tmp_ctx
,
63 ldb_search_default_callback
,
65 LDB_REQ_SET_LOCATION(req
);
66 if (ret
!= LDB_SUCCESS
) {
71 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
72 if (ret
!= LDB_SUCCESS
) {
77 if (dsdb_flags
& DSDB_FLAG_TRUSTED
) {
78 ldb_req_mark_trusted(req
);
81 /* Run the new request */
82 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
83 ret
= ldb_next_request(module
, req
);
84 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
85 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
87 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
88 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
89 ret
= ops
->search(module
, req
);
91 if (ret
== LDB_SUCCESS
) {
92 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
95 if (ret
!= LDB_SUCCESS
) {
100 if (res
->count
!= 1) {
101 /* we may be reading a DB that does not have the 'check base on search' option... */
102 ret
= LDB_ERR_NO_SUCH_OBJECT
;
103 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
104 "dsdb_module_search_dn: did not find base dn %s (%d results)",
105 ldb_dn_get_linearized(basedn
), res
->count
);
107 *_res
= talloc_steal(mem_ctx
, res
);
109 talloc_free(tmp_ctx
);
113 int dsdb_module_search_tree(struct ldb_module
*module
,
115 struct ldb_result
**_res
,
116 struct ldb_dn
*basedn
,
117 enum ldb_scope scope
,
118 struct ldb_parse_tree
*tree
,
119 const char * const *attrs
,
121 struct ldb_request
*parent
)
124 struct ldb_request
*req
;
126 struct ldb_result
*res
;
128 tmp_ctx
= talloc_new(mem_ctx
);
130 /* cross-partitions searches with a basedn break multi-domain support */
131 SMB_ASSERT(basedn
== NULL
|| (dsdb_flags
& DSDB_SEARCH_SEARCH_ALL_PARTITIONS
) == 0);
133 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
135 talloc_free(tmp_ctx
);
136 return ldb_oom(ldb_module_get_ctx(module
));
139 ret
= ldb_build_search_req_ex(&req
, ldb_module_get_ctx(module
), tmp_ctx
,
146 ldb_search_default_callback
,
148 LDB_REQ_SET_LOCATION(req
);
149 if (ret
!= LDB_SUCCESS
) {
150 talloc_free(tmp_ctx
);
154 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
155 if (ret
!= LDB_SUCCESS
) {
156 talloc_free(tmp_ctx
);
160 if (dsdb_flags
& DSDB_FLAG_TRUSTED
) {
161 ldb_req_mark_trusted(req
);
164 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
165 ret
= ldb_next_request(module
, req
);
166 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
167 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
169 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
170 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
171 ret
= ops
->search(module
, req
);
173 if (ret
== LDB_SUCCESS
) {
174 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
178 if (ret
== LDB_SUCCESS
) {
179 *_res
= talloc_steal(mem_ctx
, res
);
181 talloc_free(tmp_ctx
);
186 search for attrs in the modules below
188 int dsdb_module_search(struct ldb_module
*module
,
190 struct ldb_result
**_res
,
191 struct ldb_dn
*basedn
, enum ldb_scope scope
,
192 const char * const *attrs
,
194 struct ldb_request
*parent
,
195 const char *format
, ...) _PRINTF_ATTRIBUTE(9, 10)
201 struct ldb_parse_tree
*tree
;
203 /* cross-partitions searches with a basedn break multi-domain support */
204 SMB_ASSERT(basedn
== NULL
|| (dsdb_flags
& DSDB_SEARCH_SEARCH_ALL_PARTITIONS
) == 0);
206 tmp_ctx
= talloc_new(mem_ctx
);
209 va_start(ap
, format
);
210 expression
= talloc_vasprintf(tmp_ctx
, format
, ap
);
214 talloc_free(tmp_ctx
);
215 return ldb_oom(ldb_module_get_ctx(module
));
221 tree
= ldb_parse_tree(tmp_ctx
, expression
);
223 talloc_free(tmp_ctx
);
224 ldb_set_errstring(ldb_module_get_ctx(module
),
225 "Unable to parse search expression");
226 return LDB_ERR_OPERATIONS_ERROR
;
229 ret
= dsdb_module_search_tree(module
,
239 talloc_free(tmp_ctx
);
244 find a DN given a GUID. This searches across all partitions
246 int dsdb_module_dn_by_guid(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
,
247 const struct GUID
*guid
, struct ldb_dn
**dn
,
248 struct ldb_request
*parent
)
250 struct ldb_result
*res
;
251 const char *attrs
[] = { NULL
};
252 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
255 ret
= dsdb_module_search(module
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
257 DSDB_FLAG_NEXT_MODULE
|
258 DSDB_SEARCH_SHOW_RECYCLED
|
259 DSDB_SEARCH_SEARCH_ALL_PARTITIONS
|
260 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
,
262 "objectGUID=%s", GUID_string(tmp_ctx
, guid
));
263 if (ret
!= LDB_SUCCESS
) {
264 talloc_free(tmp_ctx
);
267 if (res
->count
== 0) {
268 talloc_free(tmp_ctx
);
269 return LDB_ERR_NO_SUCH_OBJECT
;
271 if (res
->count
!= 1) {
272 ldb_asprintf_errstring(ldb_module_get_ctx(module
), "More than one object found matching objectGUID %s\n",
273 GUID_string(tmp_ctx
, guid
));
274 talloc_free(tmp_ctx
);
275 return LDB_ERR_OPERATIONS_ERROR
;
278 *dn
= talloc_steal(mem_ctx
, res
->msgs
[0]->dn
);
280 talloc_free(tmp_ctx
);
285 find a GUID given a DN.
287 int dsdb_module_guid_by_dn(struct ldb_module
*module
, struct ldb_dn
*dn
, struct GUID
*guid
,
288 struct ldb_request
*parent
)
290 const char *attrs
[] = { NULL
};
291 struct ldb_result
*res
;
292 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
296 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
, dn
, attrs
,
297 DSDB_FLAG_NEXT_MODULE
|
298 DSDB_SEARCH_SHOW_RECYCLED
|
299 DSDB_SEARCH_SHOW_EXTENDED_DN
,
301 if (ret
!= LDB_SUCCESS
) {
302 ldb_asprintf_errstring(ldb_module_get_ctx(module
), "Failed to find GUID for %s",
303 ldb_dn_get_linearized(dn
));
304 talloc_free(tmp_ctx
);
308 status
= dsdb_get_extended_dn_guid(res
->msgs
[0]->dn
, guid
, "GUID");
309 if (!NT_STATUS_IS_OK(status
)) {
310 talloc_free(tmp_ctx
);
311 return ldb_operr(ldb_module_get_ctx(module
));
314 talloc_free(tmp_ctx
);
320 a ldb_extended request operating on modules below the
323 Note that this does not automatically start a transaction. If you
324 need a transaction the caller needs to start it as needed.
326 int dsdb_module_extended(struct ldb_module
*module
,
328 struct ldb_result
**_res
,
329 const char* oid
, void* data
,
331 struct ldb_request
*parent
)
333 struct ldb_request
*req
;
335 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
336 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
337 struct ldb_result
*res
;
343 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
345 talloc_free(tmp_ctx
);
346 return ldb_oom(ldb_module_get_ctx(module
));
349 ret
= ldb_build_extended_req(&req
, ldb
,
354 res
, ldb_extended_default_callback
,
357 LDB_REQ_SET_LOCATION(req
);
358 if (ret
!= LDB_SUCCESS
) {
359 talloc_free(tmp_ctx
);
363 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
364 if (ret
!= LDB_SUCCESS
) {
365 talloc_free(tmp_ctx
);
369 if (dsdb_flags
& DSDB_FLAG_TRUSTED
) {
370 ldb_req_mark_trusted(req
);
373 /* Run the new request */
374 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
375 ret
= ldb_next_request(module
, req
);
376 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
377 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
379 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
380 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
381 ret
= ops
->extended(module
, req
);
383 if (ret
== LDB_SUCCESS
) {
384 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
387 if (_res
!= NULL
&& ret
== LDB_SUCCESS
) {
388 (*_res
) = talloc_steal(mem_ctx
, res
);
391 talloc_free(tmp_ctx
);
397 a ldb_modify request operating on modules below the
400 int dsdb_module_modify(struct ldb_module
*module
,
401 const struct ldb_message
*message
,
403 struct ldb_request
*parent
)
405 struct ldb_request
*mod_req
;
407 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
408 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
409 struct ldb_result
*res
;
411 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
413 talloc_free(tmp_ctx
);
414 return ldb_oom(ldb_module_get_ctx(module
));
417 ret
= ldb_build_mod_req(&mod_req
, ldb
, tmp_ctx
,
421 ldb_modify_default_callback
,
423 LDB_REQ_SET_LOCATION(mod_req
);
424 if (ret
!= LDB_SUCCESS
) {
425 talloc_free(tmp_ctx
);
429 ret
= dsdb_request_add_controls(mod_req
, dsdb_flags
);
430 if (ret
!= LDB_SUCCESS
) {
431 talloc_free(tmp_ctx
);
435 if (dsdb_flags
& DSDB_FLAG_TRUSTED
) {
436 ldb_req_mark_trusted(mod_req
);
439 /* Run the new request */
440 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
441 ret
= ldb_next_request(module
, mod_req
);
442 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
443 ret
= ldb_request(ldb_module_get_ctx(module
), mod_req
);
445 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
446 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
447 ret
= ops
->modify(module
, mod_req
);
449 if (ret
== LDB_SUCCESS
) {
450 ret
= ldb_wait(mod_req
->handle
, LDB_WAIT_ALL
);
453 talloc_free(tmp_ctx
);
460 a ldb_rename request operating on modules below the
463 int dsdb_module_rename(struct ldb_module
*module
,
464 struct ldb_dn
*olddn
, struct ldb_dn
*newdn
,
466 struct ldb_request
*parent
)
468 struct ldb_request
*req
;
470 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
471 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
472 struct ldb_result
*res
;
474 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
476 talloc_free(tmp_ctx
);
477 return ldb_oom(ldb_module_get_ctx(module
));
480 ret
= ldb_build_rename_req(&req
, ldb
, tmp_ctx
,
485 ldb_modify_default_callback
,
487 LDB_REQ_SET_LOCATION(req
);
488 if (ret
!= LDB_SUCCESS
) {
489 talloc_free(tmp_ctx
);
493 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
494 if (ret
!= LDB_SUCCESS
) {
495 talloc_free(tmp_ctx
);
499 if (dsdb_flags
& DSDB_FLAG_TRUSTED
) {
500 ldb_req_mark_trusted(req
);
503 /* Run the new request */
504 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
505 ret
= ldb_next_request(module
, req
);
506 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
507 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
509 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
510 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
511 ret
= ops
->rename(module
, req
);
513 if (ret
== LDB_SUCCESS
) {
514 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
517 talloc_free(tmp_ctx
);
522 a ldb_add request operating on modules below the
525 int dsdb_module_add(struct ldb_module
*module
,
526 const struct ldb_message
*message
,
528 struct ldb_request
*parent
)
530 struct ldb_request
*req
;
532 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
533 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
534 struct ldb_result
*res
;
536 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
538 talloc_free(tmp_ctx
);
539 return ldb_oom(ldb_module_get_ctx(module
));
542 ret
= ldb_build_add_req(&req
, ldb
, tmp_ctx
,
546 ldb_modify_default_callback
,
548 LDB_REQ_SET_LOCATION(req
);
549 if (ret
!= LDB_SUCCESS
) {
550 talloc_free(tmp_ctx
);
554 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
555 if (ret
!= LDB_SUCCESS
) {
556 talloc_free(tmp_ctx
);
560 if (dsdb_flags
& DSDB_FLAG_TRUSTED
) {
561 ldb_req_mark_trusted(req
);
564 /* Run the new request */
565 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
566 ret
= ldb_next_request(module
, req
);
567 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
568 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
570 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
571 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
572 ret
= ops
->add(module
, req
);
574 if (ret
== LDB_SUCCESS
) {
575 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
578 talloc_free(tmp_ctx
);
583 a ldb_delete request operating on modules below the
586 int dsdb_module_del(struct ldb_module
*module
,
589 struct ldb_request
*parent
)
591 struct ldb_request
*req
;
593 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
594 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
595 struct ldb_result
*res
;
597 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
599 talloc_free(tmp_ctx
);
603 ret
= ldb_build_del_req(&req
, ldb
, tmp_ctx
,
607 ldb_modify_default_callback
,
609 LDB_REQ_SET_LOCATION(req
);
610 if (ret
!= LDB_SUCCESS
) {
611 talloc_free(tmp_ctx
);
615 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
616 if (ret
!= LDB_SUCCESS
) {
617 talloc_free(tmp_ctx
);
621 if (dsdb_flags
& DSDB_FLAG_TRUSTED
) {
622 ldb_req_mark_trusted(req
);
625 /* Run the new request */
626 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
627 ret
= ldb_next_request(module
, req
);
628 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
629 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
631 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
632 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
633 ret
= ops
->del(module
, req
);
635 if (ret
== LDB_SUCCESS
) {
636 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
639 talloc_free(tmp_ctx
);
644 check if a single valued link has multiple non-deleted values
646 This is needed when we will be using the RELAX control to stop
647 ldb_tdb from checking single valued links
649 int dsdb_check_single_valued_link(const struct dsdb_attribute
*attr
,
650 const struct ldb_message_element
*el
)
652 bool found_active
= false;
655 if (!(attr
->ldb_schema_attribute
->flags
& LDB_ATTR_FLAG_SINGLE_VALUE
) ||
656 el
->num_values
< 2) {
660 for (i
=0; i
<el
->num_values
; i
++) {
661 if (!dsdb_dn_is_deleted_val(&el
->values
[i
])) {
663 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
;
673 check if an optional feature is enabled on our own NTDS DN
675 Note that features can be marked as enabled in more than one
676 place. For example, the recyclebin feature is marked as enabled both
677 on the CN=Partitions,CN=Configurration object and on the NTDS DN of
678 each DC in the forest. It seems likely that it is the job of the KCC
679 to propogate between the two
681 int dsdb_check_optional_feature(struct ldb_module
*module
, struct GUID op_feature_guid
, bool *feature_enabled
)
684 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
685 struct ldb_result
*res
;
686 struct ldb_dn
*search_dn
;
687 struct GUID search_guid
;
688 const char *attrs
[] = {"msDS-EnabledFeature", NULL
};
691 struct ldb_message_element
*el
;
692 struct ldb_dn
*feature_dn
;
694 tmp_ctx
= talloc_new(ldb
);
696 feature_dn
= samdb_ntds_settings_dn(ldb_module_get_ctx(module
), tmp_ctx
);
697 if (feature_dn
== NULL
) {
698 talloc_free(tmp_ctx
);
699 return ldb_operr(ldb_module_get_ctx(module
));
702 *feature_enabled
= false;
704 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
, feature_dn
, attrs
, DSDB_FLAG_NEXT_MODULE
, NULL
);
705 if (ret
!= LDB_SUCCESS
) {
706 ldb_asprintf_errstring(ldb
,
707 "Could not find the feature object - dn: %s\n",
708 ldb_dn_get_linearized(feature_dn
));
709 talloc_free(tmp_ctx
);
710 return LDB_ERR_OPERATIONS_ERROR
;
712 if (res
->msgs
[0]->num_elements
> 0) {
713 const char *attrs2
[] = {"msDS-OptionalFeatureGUID", NULL
};
715 el
= ldb_msg_find_element(res
->msgs
[0],"msDS-EnabledFeature");
717 for (i
=0; i
<el
->num_values
; i
++) {
718 search_dn
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, &el
->values
[i
]);
720 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
,
721 search_dn
, attrs2
, DSDB_FLAG_NEXT_MODULE
, NULL
);
722 if (ret
!= LDB_SUCCESS
) {
723 ldb_asprintf_errstring(ldb
,
724 "Could no find object dn: %s\n",
725 ldb_dn_get_linearized(search_dn
));
726 talloc_free(tmp_ctx
);
727 return LDB_ERR_OPERATIONS_ERROR
;
730 search_guid
= samdb_result_guid(res
->msgs
[0], "msDS-OptionalFeatureGUID");
732 if (GUID_compare(&search_guid
, &op_feature_guid
) == 0) {
733 *feature_enabled
= true;
738 talloc_free(tmp_ctx
);
743 find the NTDS GUID from a computers DN record
745 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module
*module
,
747 struct ldb_dn
*computer_dn
,
748 struct GUID
*ntds_guid
,
749 struct ldb_request
*parent
)
754 *ntds_guid
= GUID_zero();
756 ret
= dsdb_module_reference_dn(module
, mem_ctx
, computer_dn
,
757 "serverReferenceBL", &dn
, parent
);
758 if (ret
!= LDB_SUCCESS
) {
762 if (!ldb_dn_add_child_fmt(dn
, "CN=NTDS Settings")) {
764 return LDB_ERR_OPERATIONS_ERROR
;
767 ret
= dsdb_module_guid_by_dn(module
, dn
, ntds_guid
, parent
);
773 find a 'reference' DN that points at another object
774 (eg. serverReference, rIDManagerReference etc)
776 int dsdb_module_reference_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
*base
,
777 const char *attribute
, struct ldb_dn
**dn
, struct ldb_request
*parent
)
779 const char *attrs
[2];
780 struct ldb_result
*res
;
783 attrs
[0] = attribute
;
786 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
, base
, attrs
,
787 DSDB_FLAG_NEXT_MODULE
| DSDB_SEARCH_SHOW_EXTENDED_DN
, parent
);
788 if (ret
!= LDB_SUCCESS
) {
792 *dn
= ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module
),
793 mem_ctx
, res
->msgs
[0], attribute
);
795 ldb_reset_err_string(ldb_module_get_ctx(module
));
797 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
805 find the RID Manager$ DN via the rIDManagerReference attribute in the
808 int dsdb_module_rid_manager_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
**dn
,
809 struct ldb_request
*parent
)
811 return dsdb_module_reference_dn(module
, mem_ctx
,
812 ldb_get_default_basedn(ldb_module_get_ctx(module
)),
813 "rIDManagerReference", dn
, parent
);
817 used to chain to the callers callback
819 int dsdb_next_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
821 struct ldb_request
*up_req
= talloc_get_type(req
->context
, struct ldb_request
);
823 talloc_steal(up_req
, req
);
824 return up_req
->callback(up_req
, ares
);
828 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
829 object for a partition
831 int dsdb_module_load_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
832 uint64_t *uSN
, uint64_t *urgent_uSN
, struct ldb_request
*parent
)
834 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
835 struct ldb_request
*req
;
837 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
838 struct dsdb_control_current_partition
*p_ctrl
;
839 struct ldb_result
*res
;
841 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
843 talloc_free(tmp_ctx
);
844 return ldb_module_oom(module
);
847 ret
= ldb_build_search_req(&req
, ldb
, tmp_ctx
,
848 ldb_dn_new(tmp_ctx
, ldb
, "@REPLCHANGED"),
852 res
, ldb_search_default_callback
,
854 LDB_REQ_SET_LOCATION(req
);
855 if (ret
!= LDB_SUCCESS
) {
856 talloc_free(tmp_ctx
);
860 p_ctrl
= talloc(req
, struct dsdb_control_current_partition
);
861 if (p_ctrl
== NULL
) {
862 talloc_free(tmp_ctx
);
863 return ldb_module_oom(module
);
865 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
869 ret
= ldb_request_add_control(req
,
870 DSDB_CONTROL_CURRENT_PARTITION_OID
,
872 if (ret
!= LDB_SUCCESS
) {
873 talloc_free(tmp_ctx
);
877 /* Run the new request */
878 ret
= ldb_next_request(module
, req
);
880 if (ret
== LDB_SUCCESS
) {
881 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
884 if (ret
== LDB_ERR_NO_SUCH_OBJECT
|| ret
== LDB_ERR_INVALID_DN_SYNTAX
) {
885 /* it hasn't been created yet, which means
886 an implicit value of zero */
888 talloc_free(tmp_ctx
);
889 ldb_reset_err_string(ldb
);
893 if (ret
!= LDB_SUCCESS
) {
894 talloc_free(tmp_ctx
);
898 if (res
->count
!= 1) {
904 *uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNHighest", 0);
906 *urgent_uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNUrgent", 0);
910 talloc_free(tmp_ctx
);
916 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
919 int dsdb_module_save_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
920 uint64_t uSN
, uint64_t urgent_uSN
,
921 struct ldb_request
*parent
)
923 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
924 struct ldb_request
*req
;
925 struct ldb_message
*msg
;
926 struct dsdb_control_current_partition
*p_ctrl
;
928 struct ldb_result
*res
;
930 msg
= ldb_msg_new(module
);
932 return ldb_module_oom(module
);
935 msg
->dn
= ldb_dn_new(msg
, ldb
, "@REPLCHANGED");
936 if (msg
->dn
== NULL
) {
938 return ldb_operr(ldb_module_get_ctx(module
));
941 res
= talloc_zero(msg
, struct ldb_result
);
944 return ldb_module_oom(module
);
947 ret
= samdb_msg_add_uint64(ldb
, msg
, msg
, "uSNHighest", uSN
);
948 if (ret
!= LDB_SUCCESS
) {
952 msg
->elements
[0].flags
= LDB_FLAG_MOD_REPLACE
;
954 /* urgent_uSN is optional so may not be stored */
956 ret
= samdb_msg_add_uint64(ldb
, msg
, msg
, "uSNUrgent",
958 if (ret
!= LDB_SUCCESS
) {
962 msg
->elements
[1].flags
= LDB_FLAG_MOD_REPLACE
;
966 p_ctrl
= talloc(msg
, struct dsdb_control_current_partition
);
967 if (p_ctrl
== NULL
) {
971 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
973 ret
= ldb_build_mod_req(&req
, ldb
, msg
,
977 ldb_modify_default_callback
,
979 LDB_REQ_SET_LOCATION(req
);
981 if (ret
!= LDB_SUCCESS
) {
986 ret
= ldb_request_add_control(req
,
987 DSDB_CONTROL_CURRENT_PARTITION_OID
,
989 if (ret
!= LDB_SUCCESS
) {
994 /* Run the new request */
995 ret
= ldb_next_request(module
, req
);
997 if (ret
== LDB_SUCCESS
) {
998 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
1000 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1001 ret
= ldb_build_add_req(&req
, ldb
, msg
,
1005 ldb_modify_default_callback
,
1007 LDB_REQ_SET_LOCATION(req
);
1016 bool dsdb_module_am_system(struct ldb_module
*module
)
1018 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1019 struct auth_session_info
*session_info
1020 = talloc_get_type(ldb_get_opaque(ldb
, "sessionInfo"), struct auth_session_info
);
1021 return security_session_user_level(session_info
, NULL
) == SECURITY_SYSTEM
;
1024 bool dsdb_module_am_administrator(struct ldb_module
*module
)
1026 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1027 struct auth_session_info
*session_info
1028 = talloc_get_type(ldb_get_opaque(ldb
, "sessionInfo"), struct auth_session_info
);
1029 return security_session_user_level(session_info
, NULL
) == SECURITY_ADMINISTRATOR
;
1033 check if the recyclebin is enabled
1035 int dsdb_recyclebin_enabled(struct ldb_module
*module
, bool *enabled
)
1037 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1038 struct GUID recyclebin_guid
;
1041 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN
, &recyclebin_guid
);
1043 ret
= dsdb_check_optional_feature(module
, recyclebin_guid
, enabled
);
1044 if (ret
!= LDB_SUCCESS
) {
1045 ldb_asprintf_errstring(ldb
, "Could not verify if Recycle Bin is enabled \n");
1046 return LDB_ERR_UNWILLING_TO_PERFORM
;
1052 int dsdb_msg_constrainted_update_int32(struct ldb_module
*module
,
1053 struct ldb_message
*msg
,
1055 const int32_t *old_val
,
1056 const int32_t *new_val
)
1058 struct ldb_message_element
*el
;
1063 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1064 if (ret
!= LDB_SUCCESS
) {
1068 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1070 return ldb_module_oom(module
);
1072 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*old_val
);
1074 return ldb_module_oom(module
);
1076 *el
->values
= data_blob_string_const(vstring
);
1080 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1081 if (ret
!= LDB_SUCCESS
) {
1085 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1087 return ldb_module_oom(module
);
1089 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*new_val
);
1091 return ldb_module_oom(module
);
1093 *el
->values
= data_blob_string_const(vstring
);
1099 int dsdb_msg_constrainted_update_uint32(struct ldb_module
*module
,
1100 struct ldb_message
*msg
,
1102 const uint32_t *old_val
,
1103 const uint32_t *new_val
)
1105 return dsdb_msg_constrainted_update_int32(module
, msg
, attr
,
1106 (const int32_t *)old_val
,
1107 (const int32_t *)new_val
);
1110 int dsdb_msg_constrainted_update_int64(struct ldb_module
*module
,
1111 struct ldb_message
*msg
,
1113 const int64_t *old_val
,
1114 const int64_t *new_val
)
1116 struct ldb_message_element
*el
;
1121 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1122 if (ret
!= LDB_SUCCESS
) {
1126 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1128 return ldb_module_oom(module
);
1130 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*old_val
);
1132 return ldb_module_oom(module
);
1134 *el
->values
= data_blob_string_const(vstring
);
1138 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1139 if (ret
!= LDB_SUCCESS
) {
1143 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1145 return ldb_module_oom(module
);
1147 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*new_val
);
1149 return ldb_module_oom(module
);
1151 *el
->values
= data_blob_string_const(vstring
);
1157 int dsdb_msg_constrainted_update_uint64(struct ldb_module
*module
,
1158 struct ldb_message
*msg
,
1160 const uint64_t *old_val
,
1161 const uint64_t *new_val
)
1163 return dsdb_msg_constrainted_update_int64(module
, msg
, attr
,
1164 (const int64_t *)old_val
,
1165 (const int64_t *)new_val
);
1169 update an int32 attribute safely via a constrained delete/add
1171 int dsdb_module_constrainted_update_int32(struct ldb_module
*module
,
1174 const int32_t *old_val
,
1175 const int32_t *new_val
,
1176 struct ldb_request
*parent
)
1178 struct ldb_message
*msg
;
1181 msg
= ldb_msg_new(module
);
1184 ret
= dsdb_msg_constrainted_update_int32(module
,
1188 if (ret
!= LDB_SUCCESS
) {
1193 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1198 int dsdb_module_constrainted_update_uint32(struct ldb_module
*module
,
1201 const uint32_t *old_val
,
1202 const uint32_t *new_val
,
1203 struct ldb_request
*parent
)
1205 return dsdb_module_constrainted_update_int32(module
, dn
, attr
,
1206 (const int32_t *)old_val
,
1207 (const int32_t *)new_val
, parent
);
1211 update an int64 attribute safely via a constrained delete/add
1213 int dsdb_module_constrainted_update_int64(struct ldb_module
*module
,
1216 const int64_t *old_val
,
1217 const int64_t *new_val
,
1218 struct ldb_request
*parent
)
1220 struct ldb_message
*msg
;
1223 msg
= ldb_msg_new(module
);
1226 ret
= dsdb_msg_constrainted_update_int64(module
,
1230 if (ret
!= LDB_SUCCESS
) {
1235 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1240 int dsdb_module_constrainted_update_uint64(struct ldb_module
*module
,
1243 const uint64_t *old_val
,
1244 const uint64_t *new_val
,
1245 struct ldb_request
*parent
)
1247 return dsdb_module_constrainted_update_int64(module
, dn
, attr
,
1248 (const int64_t *)old_val
,
1249 (const int64_t *)new_val
,
1254 const struct ldb_val
*dsdb_module_find_dsheuristics(struct ldb_module
*module
,
1255 TALLOC_CTX
*mem_ctx
, struct ldb_request
*parent
)
1258 struct ldb_dn
*new_dn
;
1259 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1260 static const char *attrs
[] = { "dSHeuristics", NULL
};
1261 struct ldb_result
*res
;
1263 new_dn
= ldb_dn_copy(mem_ctx
, ldb_get_config_basedn(ldb
));
1264 if (!ldb_dn_add_child_fmt(new_dn
,
1265 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1266 talloc_free(new_dn
);
1269 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
,
1272 DSDB_FLAG_NEXT_MODULE
,
1274 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1275 talloc_free(new_dn
);
1276 return ldb_msg_find_ldb_val(res
->msgs
[0],
1279 talloc_free(new_dn
);
1283 bool dsdb_block_anonymous_ops(struct ldb_module
*module
, struct ldb_request
*parent
)
1285 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
1287 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1289 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_BLOCK_ANONYMOUS_OPS
) {
1291 } else if (hr_val
->data
[DS_HR_BLOCK_ANONYMOUS_OPS
-1] == '2') {
1297 talloc_free(tmp_ctx
);
1301 bool dsdb_user_password_support(struct ldb_module
*module
,
1302 TALLOC_CTX
*mem_ctx
,
1303 struct ldb_request
*parent
)
1305 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
1307 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1310 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_USER_PASSWORD_SUPPORT
) {
1312 } else if ((hr_val
->data
[DS_HR_USER_PASSWORD_SUPPORT
-1] == '2') ||
1313 (hr_val
->data
[DS_HR_USER_PASSWORD_SUPPORT
-1] == '0')) {
1319 talloc_free(tmp_ctx
);
1324 show the chain of requests, useful for debugging async requests
1326 void dsdb_req_chain_debug(struct ldb_request
*req
, int level
)
1328 char *s
= ldb_module_call_chain(req
, req
);
1329 DEBUG(level
, ("%s\n", s
));
1334 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1335 * performing a modify operation.
1337 * In order that the constraint checking by the "objectclass_attrs" LDB module
1338 * does work properly, the change request should remain similar or only be
1339 * enhanced (no other modifications as deletions, variations).
1341 struct ldb_message_element
*dsdb_get_single_valued_attr(const struct ldb_message
*msg
,
1342 const char *attr_name
,
1343 enum ldb_request_type operation
)
1345 struct ldb_message_element
*el
= NULL
;
1348 /* We've to walk over all modification entries and consider the last
1349 * non-delete one which belongs to "attr_name".
1351 * If "el" is NULL afterwards then that means there was no interesting
1353 for (i
= 0; i
< msg
->num_elements
; i
++) {
1354 if (ldb_attr_cmp(msg
->elements
[i
].name
, attr_name
) == 0) {
1355 if ((operation
== LDB_MODIFY
) &&
1356 (LDB_FLAG_MOD_TYPE(msg
->elements
[i
].flags
)
1357 == LDB_FLAG_MOD_DELETE
)) {
1360 el
= &msg
->elements
[i
];
1368 * This function determines the (last) structural or 88 object class of a passed
1369 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1370 * Without schema this does not work and hence NULL is returned.
1372 const struct dsdb_class
*dsdb_get_last_structural_class(const struct dsdb_schema
*schema
,
1373 const struct ldb_message_element
*element
)
1375 const struct dsdb_class
*last_class
;
1377 if (schema
== NULL
) {
1381 if (element
->num_values
== 0) {
1385 last_class
= dsdb_class_by_lDAPDisplayName_ldb_val(schema
,
1386 &element
->values
[element
->num_values
-1]);
1387 if (last_class
== NULL
) {
1390 if (last_class
->objectClassCategory
> 1) {