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 feature_dn
= samdb_ntds_settings_dn(ldb_module_get_ctx(module
));
695 if (feature_dn
== NULL
) {
696 return ldb_operr(ldb_module_get_ctx(module
));
699 *feature_enabled
= false;
701 tmp_ctx
= talloc_new(ldb
);
703 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
, feature_dn
, attrs
, DSDB_FLAG_NEXT_MODULE
, NULL
);
704 if (ret
!= LDB_SUCCESS
) {
705 ldb_asprintf_errstring(ldb
,
706 "Could not find the feature object - dn: %s\n",
707 ldb_dn_get_linearized(feature_dn
));
708 talloc_free(tmp_ctx
);
709 return LDB_ERR_OPERATIONS_ERROR
;
711 if (res
->msgs
[0]->num_elements
> 0) {
712 const char *attrs2
[] = {"msDS-OptionalFeatureGUID", NULL
};
714 el
= ldb_msg_find_element(res
->msgs
[0],"msDS-EnabledFeature");
716 for (i
=0; i
<el
->num_values
; i
++) {
717 search_dn
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, &el
->values
[i
]);
719 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
,
720 search_dn
, attrs2
, DSDB_FLAG_NEXT_MODULE
, NULL
);
721 if (ret
!= LDB_SUCCESS
) {
722 ldb_asprintf_errstring(ldb
,
723 "Could no find object dn: %s\n",
724 ldb_dn_get_linearized(search_dn
));
725 talloc_free(tmp_ctx
);
726 return LDB_ERR_OPERATIONS_ERROR
;
729 search_guid
= samdb_result_guid(res
->msgs
[0], "msDS-OptionalFeatureGUID");
731 if (GUID_compare(&search_guid
, &op_feature_guid
) == 0) {
732 *feature_enabled
= true;
737 talloc_free(tmp_ctx
);
742 find the NTDS GUID from a computers DN record
744 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module
*module
,
746 struct ldb_dn
*computer_dn
,
747 struct GUID
*ntds_guid
,
748 struct ldb_request
*parent
)
753 *ntds_guid
= GUID_zero();
755 ret
= dsdb_module_reference_dn(module
, mem_ctx
, computer_dn
,
756 "serverReferenceBL", &dn
, parent
);
757 if (ret
!= LDB_SUCCESS
) {
761 if (!ldb_dn_add_child_fmt(dn
, "CN=NTDS Settings")) {
763 return LDB_ERR_OPERATIONS_ERROR
;
766 ret
= dsdb_module_guid_by_dn(module
, dn
, ntds_guid
, parent
);
772 find a 'reference' DN that points at another object
773 (eg. serverReference, rIDManagerReference etc)
775 int dsdb_module_reference_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
*base
,
776 const char *attribute
, struct ldb_dn
**dn
, struct ldb_request
*parent
)
778 const char *attrs
[2];
779 struct ldb_result
*res
;
782 attrs
[0] = attribute
;
785 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
, base
, attrs
,
786 DSDB_FLAG_NEXT_MODULE
| DSDB_SEARCH_SHOW_EXTENDED_DN
, parent
);
787 if (ret
!= LDB_SUCCESS
) {
791 *dn
= ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module
),
792 mem_ctx
, res
->msgs
[0], attribute
);
794 ldb_reset_err_string(ldb_module_get_ctx(module
));
796 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
804 find the RID Manager$ DN via the rIDManagerReference attribute in the
807 int dsdb_module_rid_manager_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
**dn
,
808 struct ldb_request
*parent
)
810 return dsdb_module_reference_dn(module
, mem_ctx
,
811 ldb_get_default_basedn(ldb_module_get_ctx(module
)),
812 "rIDManagerReference", dn
, parent
);
816 used to chain to the callers callback
818 int dsdb_next_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
820 struct ldb_request
*up_req
= talloc_get_type(req
->context
, struct ldb_request
);
822 talloc_steal(up_req
, req
);
823 return up_req
->callback(up_req
, ares
);
827 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
828 object for a partition
830 int dsdb_module_load_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
831 uint64_t *uSN
, uint64_t *urgent_uSN
, struct ldb_request
*parent
)
833 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
834 struct ldb_request
*req
;
836 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
837 struct dsdb_control_current_partition
*p_ctrl
;
838 struct ldb_result
*res
;
840 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
842 talloc_free(tmp_ctx
);
843 return ldb_module_oom(module
);
846 ret
= ldb_build_search_req(&req
, ldb
, tmp_ctx
,
847 ldb_dn_new(tmp_ctx
, ldb
, "@REPLCHANGED"),
851 res
, ldb_search_default_callback
,
853 LDB_REQ_SET_LOCATION(req
);
854 if (ret
!= LDB_SUCCESS
) {
855 talloc_free(tmp_ctx
);
859 p_ctrl
= talloc(req
, struct dsdb_control_current_partition
);
860 if (p_ctrl
== NULL
) {
861 talloc_free(tmp_ctx
);
862 return ldb_module_oom(module
);
864 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
868 ret
= ldb_request_add_control(req
,
869 DSDB_CONTROL_CURRENT_PARTITION_OID
,
871 if (ret
!= LDB_SUCCESS
) {
872 talloc_free(tmp_ctx
);
876 /* Run the new request */
877 ret
= ldb_next_request(module
, req
);
879 if (ret
== LDB_SUCCESS
) {
880 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
883 if (ret
== LDB_ERR_NO_SUCH_OBJECT
|| ret
== LDB_ERR_INVALID_DN_SYNTAX
) {
884 /* it hasn't been created yet, which means
885 an implicit value of zero */
887 talloc_free(tmp_ctx
);
888 ldb_reset_err_string(ldb
);
892 if (ret
!= LDB_SUCCESS
) {
893 talloc_free(tmp_ctx
);
897 if (res
->count
!= 1) {
903 *uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNHighest", 0);
905 *urgent_uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNUrgent", 0);
909 talloc_free(tmp_ctx
);
915 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
918 int dsdb_module_save_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
919 uint64_t uSN
, uint64_t urgent_uSN
,
920 struct ldb_request
*parent
)
922 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
923 struct ldb_request
*req
;
924 struct ldb_message
*msg
;
925 struct dsdb_control_current_partition
*p_ctrl
;
927 struct ldb_result
*res
;
929 msg
= ldb_msg_new(module
);
931 return ldb_module_oom(module
);
934 msg
->dn
= ldb_dn_new(msg
, ldb
, "@REPLCHANGED");
935 if (msg
->dn
== NULL
) {
937 return ldb_operr(ldb_module_get_ctx(module
));
940 res
= talloc_zero(msg
, struct ldb_result
);
943 return ldb_module_oom(module
);
946 ret
= samdb_msg_add_uint64(ldb
, msg
, msg
, "uSNHighest", uSN
);
947 if (ret
!= LDB_SUCCESS
) {
951 msg
->elements
[0].flags
= LDB_FLAG_MOD_REPLACE
;
953 /* urgent_uSN is optional so may not be stored */
955 ret
= samdb_msg_add_uint64(ldb
, msg
, msg
, "uSNUrgent",
957 if (ret
!= LDB_SUCCESS
) {
961 msg
->elements
[1].flags
= LDB_FLAG_MOD_REPLACE
;
965 p_ctrl
= talloc(msg
, struct dsdb_control_current_partition
);
966 if (p_ctrl
== NULL
) {
970 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
972 ret
= ldb_build_mod_req(&req
, ldb
, msg
,
976 ldb_modify_default_callback
,
978 LDB_REQ_SET_LOCATION(req
);
980 if (ret
!= LDB_SUCCESS
) {
985 ret
= ldb_request_add_control(req
,
986 DSDB_CONTROL_CURRENT_PARTITION_OID
,
988 if (ret
!= LDB_SUCCESS
) {
993 /* Run the new request */
994 ret
= ldb_next_request(module
, req
);
996 if (ret
== LDB_SUCCESS
) {
997 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
999 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1000 ret
= ldb_build_add_req(&req
, ldb
, msg
,
1004 ldb_modify_default_callback
,
1006 LDB_REQ_SET_LOCATION(req
);
1015 bool dsdb_module_am_system(struct ldb_module
*module
)
1017 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1018 struct auth_session_info
*session_info
1019 = talloc_get_type(ldb_get_opaque(ldb
, "sessionInfo"), struct auth_session_info
);
1020 return security_session_user_level(session_info
, NULL
) == SECURITY_SYSTEM
;
1023 bool dsdb_module_am_administrator(struct ldb_module
*module
)
1025 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1026 struct auth_session_info
*session_info
1027 = talloc_get_type(ldb_get_opaque(ldb
, "sessionInfo"), struct auth_session_info
);
1028 return security_session_user_level(session_info
, NULL
) == SECURITY_ADMINISTRATOR
;
1032 check if the recyclebin is enabled
1034 int dsdb_recyclebin_enabled(struct ldb_module
*module
, bool *enabled
)
1036 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1037 struct GUID recyclebin_guid
;
1040 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN
, &recyclebin_guid
);
1042 ret
= dsdb_check_optional_feature(module
, recyclebin_guid
, enabled
);
1043 if (ret
!= LDB_SUCCESS
) {
1044 ldb_asprintf_errstring(ldb
, "Could not verify if Recycle Bin is enabled \n");
1045 return LDB_ERR_UNWILLING_TO_PERFORM
;
1051 int dsdb_msg_constrainted_update_int32(struct ldb_module
*module
,
1052 struct ldb_message
*msg
,
1054 const int32_t *old_val
,
1055 const int32_t *new_val
)
1057 struct ldb_message_element
*el
;
1062 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1063 if (ret
!= LDB_SUCCESS
) {
1067 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1069 return ldb_module_oom(module
);
1071 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*old_val
);
1073 return ldb_module_oom(module
);
1075 *el
->values
= data_blob_string_const(vstring
);
1079 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1080 if (ret
!= LDB_SUCCESS
) {
1084 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1086 return ldb_module_oom(module
);
1088 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*new_val
);
1090 return ldb_module_oom(module
);
1092 *el
->values
= data_blob_string_const(vstring
);
1098 int dsdb_msg_constrainted_update_uint32(struct ldb_module
*module
,
1099 struct ldb_message
*msg
,
1101 const uint32_t *old_val
,
1102 const uint32_t *new_val
)
1104 return dsdb_msg_constrainted_update_int32(module
, msg
, attr
,
1105 (const int32_t *)old_val
,
1106 (const int32_t *)new_val
);
1109 int dsdb_msg_constrainted_update_int64(struct ldb_module
*module
,
1110 struct ldb_message
*msg
,
1112 const int64_t *old_val
,
1113 const int64_t *new_val
)
1115 struct ldb_message_element
*el
;
1120 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1121 if (ret
!= LDB_SUCCESS
) {
1125 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1127 return ldb_module_oom(module
);
1129 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*old_val
);
1131 return ldb_module_oom(module
);
1133 *el
->values
= data_blob_string_const(vstring
);
1137 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1138 if (ret
!= LDB_SUCCESS
) {
1142 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1144 return ldb_module_oom(module
);
1146 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*new_val
);
1148 return ldb_module_oom(module
);
1150 *el
->values
= data_blob_string_const(vstring
);
1156 int dsdb_msg_constrainted_update_uint64(struct ldb_module
*module
,
1157 struct ldb_message
*msg
,
1159 const uint64_t *old_val
,
1160 const uint64_t *new_val
)
1162 return dsdb_msg_constrainted_update_int64(module
, msg
, attr
,
1163 (const int64_t *)old_val
,
1164 (const int64_t *)new_val
);
1168 update an int32 attribute safely via a constrained delete/add
1170 int dsdb_module_constrainted_update_int32(struct ldb_module
*module
,
1173 const int32_t *old_val
,
1174 const int32_t *new_val
,
1175 struct ldb_request
*parent
)
1177 struct ldb_message
*msg
;
1180 msg
= ldb_msg_new(module
);
1183 ret
= dsdb_msg_constrainted_update_int32(module
,
1187 if (ret
!= LDB_SUCCESS
) {
1192 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1197 int dsdb_module_constrainted_update_uint32(struct ldb_module
*module
,
1200 const uint32_t *old_val
,
1201 const uint32_t *new_val
,
1202 struct ldb_request
*parent
)
1204 return dsdb_module_constrainted_update_int32(module
, dn
, attr
,
1205 (const int32_t *)old_val
,
1206 (const int32_t *)new_val
, parent
);
1210 update an int64 attribute safely via a constrained delete/add
1212 int dsdb_module_constrainted_update_int64(struct ldb_module
*module
,
1215 const int64_t *old_val
,
1216 const int64_t *new_val
,
1217 struct ldb_request
*parent
)
1219 struct ldb_message
*msg
;
1222 msg
= ldb_msg_new(module
);
1225 ret
= dsdb_msg_constrainted_update_int64(module
,
1229 if (ret
!= LDB_SUCCESS
) {
1234 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1239 int dsdb_module_constrainted_update_uint64(struct ldb_module
*module
,
1242 const uint64_t *old_val
,
1243 const uint64_t *new_val
,
1244 struct ldb_request
*parent
)
1246 return dsdb_module_constrainted_update_int64(module
, dn
, attr
,
1247 (const int64_t *)old_val
,
1248 (const int64_t *)new_val
,
1253 const struct ldb_val
*dsdb_module_find_dsheuristics(struct ldb_module
*module
,
1254 TALLOC_CTX
*mem_ctx
, struct ldb_request
*parent
)
1257 struct ldb_dn
*new_dn
;
1258 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1259 static const char *attrs
[] = { "dSHeuristics", NULL
};
1260 struct ldb_result
*res
;
1262 new_dn
= ldb_dn_copy(mem_ctx
, ldb_get_config_basedn(ldb
));
1263 if (!ldb_dn_add_child_fmt(new_dn
,
1264 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1265 talloc_free(new_dn
);
1268 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
,
1271 DSDB_FLAG_NEXT_MODULE
,
1273 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1274 talloc_free(new_dn
);
1275 return ldb_msg_find_ldb_val(res
->msgs
[0],
1278 talloc_free(new_dn
);
1282 bool dsdb_block_anonymous_ops(struct ldb_module
*module
, struct ldb_request
*parent
)
1284 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
1286 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1288 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_BLOCK_ANONYMOUS_OPS
) {
1290 } else if (hr_val
->data
[DS_HR_BLOCK_ANONYMOUS_OPS
-1] == '2') {
1296 talloc_free(tmp_ctx
);
1300 bool dsdb_user_password_support(struct ldb_module
*module
,
1301 TALLOC_CTX
*mem_ctx
,
1302 struct ldb_request
*parent
)
1304 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
1306 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1309 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_USER_PASSWORD_SUPPORT
) {
1311 } else if ((hr_val
->data
[DS_HR_USER_PASSWORD_SUPPORT
-1] == '2') ||
1312 (hr_val
->data
[DS_HR_USER_PASSWORD_SUPPORT
-1] == '0')) {
1318 talloc_free(tmp_ctx
);
1323 show the chain of requests, useful for debugging async requests
1325 void dsdb_req_chain_debug(struct ldb_request
*req
, int level
)
1327 char *s
= ldb_module_call_chain(req
, req
);
1328 DEBUG(level
, ("%s\n", s
));
1333 * Gets back a single-valued attribute by the rules of the DSDB triggers when
1334 * performing a modify operation.
1336 * In order that the constraint checking by the "objectclass_attrs" LDB module
1337 * does work properly, the change request should remain similar or only be
1338 * enhanced (no other modifications as deletions, variations).
1340 struct ldb_message_element
*dsdb_get_single_valued_attr(const struct ldb_message
*msg
,
1341 const char *attr_name
,
1342 enum ldb_request_type operation
)
1344 struct ldb_message_element
*el
= NULL
;
1347 /* We've to walk over all modification entries and consider the last
1348 * non-delete one which belongs to "attr_name".
1350 * If "el" is NULL afterwards then that means there was no interesting
1352 for (i
= 0; i
< msg
->num_elements
; i
++) {
1353 if (ldb_attr_cmp(msg
->elements
[i
].name
, attr_name
) == 0) {
1354 if ((operation
== LDB_MODIFY
) &&
1355 (LDB_FLAG_MOD_TYPE(msg
->elements
[i
].flags
)
1356 == LDB_FLAG_MOD_DELETE
)) {
1359 el
= &msg
->elements
[i
];