2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 2009
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "ldb_module.h"
25 #include "librpc/ndr/libndr.h"
26 #include "dsdb/samdb/ldb_modules/util.h"
27 #include "dsdb/samdb/samdb.h"
29 #include "libcli/security/security.h"
30 #include "lib/ldb/include/ldb_private.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
,
43 struct ldb_request
*req
;
45 struct ldb_result
*res
;
47 tmp_ctx
= talloc_new(mem_ctx
);
49 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
52 return ldb_oom(ldb_module_get_ctx(module
));
55 ret
= ldb_build_search_req(&req
, ldb_module_get_ctx(module
), tmp_ctx
,
62 ldb_search_default_callback
,
64 if (ret
!= LDB_SUCCESS
) {
69 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
70 if (ret
!= LDB_SUCCESS
) {
75 /* Run the new request */
76 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
77 ret
= ldb_next_request(module
, req
);
78 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
79 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
81 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
82 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
83 ret
= ops
->search(module
, req
);
85 if (ret
== LDB_SUCCESS
) {
86 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
89 if (ret
!= LDB_SUCCESS
) {
94 if (res
->count
!= 1) {
95 /* we may be reading a DB that does not have the 'check base on search' option... */
96 ret
= LDB_ERR_NO_SUCH_OBJECT
;
97 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
98 "dsdb_module_search_dn: did not find base dn %s (%d results)",
99 ldb_dn_get_linearized(basedn
), res
->count
);
101 *_res
= talloc_steal(mem_ctx
, res
);
103 talloc_free(tmp_ctx
);
108 search for attrs in the modules below
110 int dsdb_module_search(struct ldb_module
*module
,
112 struct ldb_result
**_res
,
113 struct ldb_dn
*basedn
, enum ldb_scope scope
,
114 const char * const *attrs
,
116 const char *format
, ...) _PRINTF_ATTRIBUTE(8, 9)
119 struct ldb_request
*req
;
121 struct ldb_result
*res
;
125 tmp_ctx
= talloc_new(mem_ctx
);
128 va_start(ap
, format
);
129 expression
= talloc_vasprintf(tmp_ctx
, format
, ap
);
133 talloc_free(tmp_ctx
);
134 return ldb_oom(ldb_module_get_ctx(module
));
140 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
142 talloc_free(tmp_ctx
);
143 return ldb_oom(ldb_module_get_ctx(module
));
146 ret
= ldb_build_search_req(&req
, ldb_module_get_ctx(module
), tmp_ctx
,
153 ldb_search_default_callback
,
155 if (ret
!= LDB_SUCCESS
) {
156 talloc_free(tmp_ctx
);
160 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
161 if (ret
!= LDB_SUCCESS
) {
162 talloc_free(tmp_ctx
);
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
);
180 if (ret
== LDB_SUCCESS
) {
181 *_res
= talloc_steal(mem_ctx
, res
);
183 talloc_free(tmp_ctx
);
188 find a DN given a GUID. This searches across all partitions
190 int dsdb_module_dn_by_guid(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
,
191 const struct GUID
*guid
, struct ldb_dn
**dn
)
193 struct ldb_result
*res
;
194 const char *attrs
[] = { NULL
};
195 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
198 ret
= dsdb_module_search(module
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
200 DSDB_FLAG_NEXT_MODULE
|
201 DSDB_SEARCH_SHOW_DELETED
|
202 DSDB_SEARCH_SEARCH_ALL_PARTITIONS
|
203 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
,
204 "objectGUID=%s", GUID_string(tmp_ctx
, guid
));
205 if (ret
!= LDB_SUCCESS
) {
206 talloc_free(tmp_ctx
);
209 if (res
->count
== 0) {
210 talloc_free(tmp_ctx
);
211 return LDB_ERR_NO_SUCH_OBJECT
;
213 if (res
->count
!= 1) {
214 ldb_asprintf_errstring(ldb_module_get_ctx(module
), "More than one object found matching objectGUID %s\n",
215 GUID_string(tmp_ctx
, guid
));
216 talloc_free(tmp_ctx
);
217 return LDB_ERR_OPERATIONS_ERROR
;
220 *dn
= talloc_steal(mem_ctx
, res
->msgs
[0]->dn
);
222 talloc_free(tmp_ctx
);
227 find a GUID given a DN.
229 int dsdb_module_guid_by_dn(struct ldb_module
*module
, struct ldb_dn
*dn
, struct GUID
*guid
)
231 const char *attrs
[] = { NULL
};
232 struct ldb_result
*res
;
233 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
237 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
, dn
, attrs
,
238 DSDB_FLAG_NEXT_MODULE
|
239 DSDB_SEARCH_SHOW_DELETED
|
240 DSDB_SEARCH_SHOW_EXTENDED_DN
);
241 if (ret
!= LDB_SUCCESS
) {
242 ldb_asprintf_errstring(ldb_module_get_ctx(module
), "Failed to find GUID for %s",
243 ldb_dn_get_linearized(dn
));
244 talloc_free(tmp_ctx
);
248 status
= dsdb_get_extended_dn_guid(res
->msgs
[0]->dn
, guid
, "GUID");
249 if (!NT_STATUS_IS_OK(status
)) {
250 talloc_free(tmp_ctx
);
251 return ldb_operr(ldb_module_get_ctx(module
));
254 talloc_free(tmp_ctx
);
259 a ldb_modify request operating on modules below the
262 int dsdb_module_modify(struct ldb_module
*module
,
263 const struct ldb_message
*message
,
266 struct ldb_request
*mod_req
;
268 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
269 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
270 struct ldb_result
*res
;
272 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
274 talloc_free(tmp_ctx
);
275 return ldb_oom(ldb_module_get_ctx(module
));
278 ret
= ldb_build_mod_req(&mod_req
, ldb
, tmp_ctx
,
282 ldb_modify_default_callback
,
284 if (ret
!= LDB_SUCCESS
) {
285 talloc_free(tmp_ctx
);
289 ret
= dsdb_request_add_controls(mod_req
, dsdb_flags
);
290 if (ret
!= LDB_SUCCESS
) {
291 talloc_free(tmp_ctx
);
295 /* Run the new request */
296 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
297 ret
= ldb_next_request(module
, mod_req
);
298 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
299 ret
= ldb_request(ldb_module_get_ctx(module
), mod_req
);
301 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
302 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
303 ret
= ops
->modify(module
, mod_req
);
305 if (ret
== LDB_SUCCESS
) {
306 ret
= ldb_wait(mod_req
->handle
, LDB_WAIT_ALL
);
309 talloc_free(tmp_ctx
);
316 a ldb_rename request operating on modules below the
319 int dsdb_module_rename(struct ldb_module
*module
,
320 struct ldb_dn
*olddn
, struct ldb_dn
*newdn
,
323 struct ldb_request
*req
;
325 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
326 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
327 struct ldb_result
*res
;
329 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
331 talloc_free(tmp_ctx
);
332 return ldb_oom(ldb_module_get_ctx(module
));
335 ret
= ldb_build_rename_req(&req
, ldb
, tmp_ctx
,
340 ldb_modify_default_callback
,
342 if (ret
!= LDB_SUCCESS
) {
343 talloc_free(tmp_ctx
);
347 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
348 if (ret
!= LDB_SUCCESS
) {
349 talloc_free(tmp_ctx
);
353 /* Run the new request */
354 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
355 ret
= ldb_next_request(module
, req
);
356 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
357 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
359 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
360 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
361 ret
= ops
->rename(module
, req
);
363 if (ret
== LDB_SUCCESS
) {
364 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
367 talloc_free(tmp_ctx
);
372 a ldb_add request operating on modules below the
375 int dsdb_module_add(struct ldb_module
*module
,
376 const struct ldb_message
*message
,
379 struct ldb_request
*req
;
381 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
382 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
383 struct ldb_result
*res
;
385 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
387 talloc_free(tmp_ctx
);
388 return ldb_oom(ldb_module_get_ctx(module
));
391 ret
= ldb_build_add_req(&req
, ldb
, tmp_ctx
,
395 ldb_modify_default_callback
,
397 if (ret
!= LDB_SUCCESS
) {
398 talloc_free(tmp_ctx
);
402 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
403 if (ret
!= LDB_SUCCESS
) {
404 talloc_free(tmp_ctx
);
408 /* Run the new request */
409 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
410 ret
= ldb_next_request(module
, req
);
411 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
412 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
414 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
415 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
416 ret
= ops
->add(module
, req
);
418 if (ret
== LDB_SUCCESS
) {
419 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
422 talloc_free(tmp_ctx
);
427 a ldb_delete request operating on modules below the
430 int dsdb_module_del(struct ldb_module
*module
,
434 struct ldb_request
*req
;
436 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
437 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
438 struct ldb_result
*res
;
440 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
442 talloc_free(tmp_ctx
);
446 ret
= ldb_build_del_req(&req
, ldb
, tmp_ctx
,
450 ldb_modify_default_callback
,
452 if (ret
!= LDB_SUCCESS
) {
453 talloc_free(tmp_ctx
);
457 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
458 if (ret
!= LDB_SUCCESS
) {
459 talloc_free(tmp_ctx
);
463 /* Run the new request */
464 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
465 ret
= ldb_next_request(module
, req
);
466 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
467 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
469 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
470 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
471 ret
= ops
->del(module
, req
);
473 if (ret
== LDB_SUCCESS
) {
474 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
477 talloc_free(tmp_ctx
);
481 const struct dsdb_class
* get_last_structural_class(const struct dsdb_schema
*schema
,const struct ldb_message_element
*element
)
483 const struct dsdb_class
*last_class
= NULL
;
486 for (i
= 0; i
< element
->num_values
; i
++){
487 const struct dsdb_class
*tmp_class
= dsdb_class_by_lDAPDisplayName_ldb_val(schema
, &element
->values
[i
]);
489 if(tmp_class
== NULL
) {
493 if(tmp_class
->objectClassCategory
> 1) {
498 last_class
= tmp_class
;
500 if (tmp_class
->subClass_order
> last_class
->subClass_order
)
501 last_class
= tmp_class
;
509 check if a single valued link has multiple non-deleted values
511 This is needed when we will be using the RELAX control to stop
512 ldb_tdb from checking single valued links
514 int dsdb_check_single_valued_link(const struct dsdb_attribute
*attr
,
515 const struct ldb_message_element
*el
)
517 bool found_active
= false;
520 if (!(attr
->ldb_schema_attribute
->flags
& LDB_ATTR_FLAG_SINGLE_VALUE
) ||
521 el
->num_values
< 2) {
525 for (i
=0; i
<el
->num_values
; i
++) {
526 if (!dsdb_dn_is_deleted_val(&el
->values
[i
])) {
528 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
;
537 int dsdb_check_optional_feature(struct ldb_module
*module
, struct ldb_dn
*scope
,
538 struct GUID op_feature_guid
, bool *feature_enabled
)
541 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
542 struct ldb_result
*res
;
543 struct ldb_dn
*search_dn
;
544 struct GUID search_guid
;
545 const char *attrs
[] = {"msDS-EnabledFeature", NULL
};
548 struct ldb_message_element
*el
;
550 *feature_enabled
= false;
552 tmp_ctx
= talloc_new(ldb
);
554 ret
= ldb_search(ldb
, tmp_ctx
, &res
,
555 scope
, LDB_SCOPE_BASE
, attrs
,
557 if (ret
!= LDB_SUCCESS
) {
558 ldb_asprintf_errstring(ldb
,
559 "Could no find the scope object - dn: %s\n",
560 ldb_dn_get_linearized(scope
));
561 talloc_free(tmp_ctx
);
562 return LDB_ERR_OPERATIONS_ERROR
;
564 if (res
->msgs
[0]->num_elements
> 0) {
566 el
= ldb_msg_find_element(res
->msgs
[0],"msDS-EnabledFeature");
568 attrs
[0] = "msDS-OptionalFeatureGUID";
570 for (i
=0; i
<el
->num_values
; i
++) {
571 search_dn
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, &el
->values
[i
]);
573 ret
= ldb_search(ldb
, tmp_ctx
, &res
,
574 search_dn
, LDB_SCOPE_BASE
, attrs
,
576 if (ret
!= LDB_SUCCESS
) {
577 ldb_asprintf_errstring(ldb
,
578 "Could no find object dn: %s\n",
579 ldb_dn_get_linearized(search_dn
));
580 talloc_free(tmp_ctx
);
581 return LDB_ERR_OPERATIONS_ERROR
;
584 search_guid
= samdb_result_guid(res
->msgs
[0], "msDS-OptionalFeatureGUID");
586 if (GUID_compare(&search_guid
, &op_feature_guid
) == 0){
587 *feature_enabled
= true;
592 talloc_free(tmp_ctx
);
597 find a 'reference' DN that points at another object
598 (eg. serverReference, rIDManagerReference etc)
600 int dsdb_module_reference_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
*base
,
601 const char *attribute
, struct ldb_dn
**dn
)
603 const char *attrs
[2];
604 struct ldb_result
*res
;
607 attrs
[0] = attribute
;
610 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
, base
, attrs
,
611 DSDB_FLAG_NEXT_MODULE
);
612 if (ret
!= LDB_SUCCESS
) {
616 *dn
= ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module
),
617 mem_ctx
, res
->msgs
[0], attribute
);
620 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
628 find the RID Manager$ DN via the rIDManagerReference attribute in the
631 int dsdb_module_rid_manager_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
**dn
)
633 return dsdb_module_reference_dn(module
, mem_ctx
,
634 ldb_get_default_basedn(ldb_module_get_ctx(module
)),
635 "rIDManagerReference", dn
);
640 update an integer attribute safely via a constrained delete/add
642 int dsdb_module_constrainted_update_integer(struct ldb_module
*module
, struct ldb_dn
*dn
,
643 const char *attr
, uint64_t old_val
, uint64_t new_val
)
645 struct ldb_message
*msg
;
646 struct ldb_message_element
*el
;
647 struct ldb_val v1
, v2
;
651 msg
= ldb_msg_new(module
);
654 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
655 if (ret
!= LDB_SUCCESS
) {
661 vstring
= talloc_asprintf(msg
, "%llu", (unsigned long long)old_val
);
664 return ldb_module_oom(module
);
666 v1
= data_blob_string_const(vstring
);
668 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
669 if (ret
!= LDB_SUCCESS
) {
675 vstring
= talloc_asprintf(msg
, "%llu", (unsigned long long)new_val
);
678 return ldb_module_oom(module
);
680 v2
= data_blob_string_const(vstring
);
682 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
688 used to chain to the callers callback
690 int dsdb_next_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
692 struct ldb_request
*up_req
= talloc_get_type(req
->context
, struct ldb_request
);
694 talloc_steal(up_req
, req
);
695 return up_req
->callback(up_req
, ares
);
700 set an integer attribute
702 int dsdb_module_set_integer(struct ldb_module
*module
, struct ldb_dn
*dn
,
703 const char *attr
, uint64_t new_val
)
705 struct ldb_message
*msg
;
708 msg
= ldb_msg_new(module
);
711 ret
= ldb_msg_add_fmt(msg
, attr
, "%llu", (unsigned long long)new_val
);
712 if (ret
!= LDB_SUCCESS
) {
716 msg
->elements
[0].flags
= LDB_FLAG_MOD_REPLACE
;
718 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
724 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
725 object for a partition
727 int dsdb_module_load_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
728 uint64_t *uSN
, uint64_t *urgent_uSN
)
730 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
731 struct ldb_request
*req
;
733 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
734 struct dsdb_control_current_partition
*p_ctrl
;
735 struct ldb_result
*res
;
737 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
739 talloc_free(tmp_ctx
);
740 return ldb_module_oom(module
);
743 ret
= ldb_build_search_req(&req
, ldb
, tmp_ctx
,
744 ldb_dn_new(tmp_ctx
, ldb
, "@REPLCHANGED"),
748 res
, ldb_search_default_callback
,
750 if (ret
!= LDB_SUCCESS
) {
751 talloc_free(tmp_ctx
);
755 p_ctrl
= talloc(req
, struct dsdb_control_current_partition
);
756 if (p_ctrl
== NULL
) {
757 talloc_free(tmp_ctx
);
758 return ldb_module_oom(module
);
760 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
764 ret
= ldb_request_add_control(req
,
765 DSDB_CONTROL_CURRENT_PARTITION_OID
,
767 if (ret
!= LDB_SUCCESS
) {
768 talloc_free(tmp_ctx
);
772 /* Run the new request */
773 ret
= ldb_next_request(module
, req
);
775 if (ret
== LDB_SUCCESS
) {
776 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
779 if (ret
== LDB_ERR_NO_SUCH_OBJECT
|| ret
== LDB_ERR_INVALID_DN_SYNTAX
) {
780 /* it hasn't been created yet, which means
781 an implicit value of zero */
783 talloc_free(tmp_ctx
);
787 if (ret
!= LDB_SUCCESS
) {
788 talloc_free(tmp_ctx
);
792 if (res
->count
!= 1) {
798 *uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNHighest", 0);
800 *urgent_uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNUrgent", 0);
804 talloc_free(tmp_ctx
);
810 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
813 int dsdb_module_save_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
814 uint64_t uSN
, uint64_t urgent_uSN
)
816 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
817 struct ldb_request
*req
;
818 struct ldb_message
*msg
;
819 struct dsdb_control_current_partition
*p_ctrl
;
821 struct ldb_result
*res
;
823 msg
= ldb_msg_new(module
);
825 return ldb_module_oom(module
);
828 msg
->dn
= ldb_dn_new(msg
, ldb
, "@REPLCHANGED");
829 if (msg
->dn
== NULL
) {
831 return ldb_operr(ldb_module_get_ctx(module
));
834 res
= talloc_zero(msg
, struct ldb_result
);
837 return ldb_module_oom(module
);
840 ret
= ldb_msg_add_fmt(msg
, "uSNHighest", "%llu", (unsigned long long)uSN
);
841 if (ret
!= LDB_SUCCESS
) {
845 msg
->elements
[0].flags
= LDB_FLAG_MOD_REPLACE
;
847 /* urgent_uSN is optional so may not be stored */
849 ret
= ldb_msg_add_fmt(msg
, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN
);
850 if (ret
!= LDB_SUCCESS
) {
854 msg
->elements
[1].flags
= LDB_FLAG_MOD_REPLACE
;
858 p_ctrl
= talloc(msg
, struct dsdb_control_current_partition
);
859 if (p_ctrl
== NULL
) {
863 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
865 ret
= ldb_build_mod_req(&req
, ldb
, msg
,
869 ldb_modify_default_callback
,
872 if (ret
!= LDB_SUCCESS
) {
877 ret
= ldb_request_add_control(req
,
878 DSDB_CONTROL_CURRENT_PARTITION_OID
,
880 if (ret
!= LDB_SUCCESS
) {
885 /* Run the new request */
886 ret
= ldb_next_request(module
, req
);
888 if (ret
== LDB_SUCCESS
) {
889 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
891 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
892 ret
= ldb_build_add_req(&req
, ldb
, msg
,
896 ldb_modify_default_callback
,
906 bool dsdb_module_am_system(struct ldb_module
*module
)
908 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
909 struct auth_session_info
*session_info
910 = talloc_get_type(ldb_get_opaque(ldb
, "sessionInfo"), struct auth_session_info
);
911 return security_session_user_level(session_info
, NULL
) == SECURITY_SYSTEM
;
914 bool dsdb_module_am_administrator(struct ldb_module
*module
)
916 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
917 struct auth_session_info
*session_info
918 = talloc_get_type(ldb_get_opaque(ldb
, "sessionInfo"), struct auth_session_info
);
919 return security_session_user_level(session_info
, NULL
) == SECURITY_ADMINISTRATOR
;
923 check if the recyclebin is enabled
925 int dsdb_recyclebin_enabled(struct ldb_module
*module
, bool *enabled
)
927 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
928 struct ldb_dn
*partitions_dn
;
929 struct GUID recyclebin_guid
;
932 partitions_dn
= samdb_partitions_dn(ldb
, module
);
934 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN
, &recyclebin_guid
);
936 ret
= dsdb_check_optional_feature(module
, partitions_dn
, recyclebin_guid
, enabled
);
937 if (ret
!= LDB_SUCCESS
) {
938 ldb_asprintf_errstring(ldb
, "Could not verify if Recycle Bin is enabled \n");
939 talloc_free(partitions_dn
);
940 return LDB_ERR_UNWILLING_TO_PERFORM
;
943 talloc_free(partitions_dn
);
947 bool is_attr_in_list(const char * const * attrs
, const char *attr
)
951 for (i
= 0; attrs
[i
]; i
++) {
952 if (ldb_attr_cmp(attrs
[i
], attr
) == 0)
959 int dsdb_msg_constrainted_update_int32(struct ldb_module
*module
,
960 struct ldb_message
*msg
,
962 const int32_t *old_val
,
963 const int32_t *new_val
)
965 struct ldb_message_element
*el
;
970 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
971 if (ret
!= LDB_SUCCESS
) {
975 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
977 return ldb_module_oom(module
);
979 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*old_val
);
981 return ldb_module_oom(module
);
983 *el
->values
= data_blob_string_const(vstring
);
987 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
988 if (ret
!= LDB_SUCCESS
) {
992 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
994 return ldb_module_oom(module
);
996 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*new_val
);
998 return ldb_module_oom(module
);
1000 *el
->values
= data_blob_string_const(vstring
);
1006 int dsdb_msg_constrainted_update_uint32(struct ldb_module
*module
,
1007 struct ldb_message
*msg
,
1009 const uint32_t *old_val
,
1010 const uint32_t *new_val
)
1012 return dsdb_msg_constrainted_update_int32(module
, msg
, attr
,
1013 (const int32_t *)old_val
,
1014 (const int32_t *)new_val
);
1017 int dsdb_msg_constrainted_update_int64(struct ldb_module
*module
,
1018 struct ldb_message
*msg
,
1020 const int64_t *old_val
,
1021 const int64_t *new_val
)
1023 struct ldb_message_element
*el
;
1028 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1029 if (ret
!= LDB_SUCCESS
) {
1033 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1035 return ldb_module_oom(module
);
1037 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*old_val
);
1039 return ldb_module_oom(module
);
1041 *el
->values
= data_blob_string_const(vstring
);
1045 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1046 if (ret
!= LDB_SUCCESS
) {
1050 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1052 return ldb_module_oom(module
);
1054 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*new_val
);
1056 return ldb_module_oom(module
);
1058 *el
->values
= data_blob_string_const(vstring
);
1064 int dsdb_msg_constrainted_update_uint64(struct ldb_module
*module
,
1065 struct ldb_message
*msg
,
1067 const uint64_t *old_val
,
1068 const uint64_t *new_val
)
1070 return dsdb_msg_constrainted_update_int64(module
, msg
, attr
,
1071 (const int64_t *)old_val
,
1072 (const int64_t *)new_val
);
1076 update an int32 attribute safely via a constrained delete/add
1078 int dsdb_module_constrainted_update_int32(struct ldb_module
*module
,
1081 const int32_t *old_val
,
1082 const int32_t *new_val
)
1084 struct ldb_message
*msg
;
1087 msg
= ldb_msg_new(module
);
1090 ret
= dsdb_msg_constrainted_update_int32(module
,
1094 if (ret
!= LDB_SUCCESS
) {
1099 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
1104 int dsdb_module_constrainted_update_uint32(struct ldb_module
*module
,
1107 const uint32_t *old_val
,
1108 const uint32_t *new_val
)
1110 return dsdb_module_constrainted_update_int32(module
, dn
, attr
,
1111 (const int32_t *)old_val
,
1112 (const int32_t *)new_val
);
1116 update an int64 attribute safely via a constrained delete/add
1118 int dsdb_module_constrainted_update_int64(struct ldb_module
*module
,
1121 const int64_t *old_val
,
1122 const int64_t *new_val
)
1124 struct ldb_message
*msg
;
1127 msg
= ldb_msg_new(module
);
1130 ret
= dsdb_msg_constrainted_update_int64(module
,
1134 if (ret
!= LDB_SUCCESS
) {
1139 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
1144 int dsdb_module_constrainted_update_uint64(struct ldb_module
*module
,
1147 const uint64_t *old_val
,
1148 const uint64_t *new_val
)
1150 return dsdb_module_constrainted_update_int64(module
, dn
, attr
,
1151 (const int64_t *)old_val
,
1152 (const int64_t *)new_val
);
1156 const struct ldb_val
*dsdb_module_find_dsheuristics(struct ldb_module
*module
,
1157 TALLOC_CTX
*mem_ctx
)
1160 struct ldb_dn
*new_dn
;
1161 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1162 static const char *attrs
[] = { "dsHeuristics", NULL
};
1163 struct ldb_result
*res
;
1165 new_dn
= ldb_dn_copy(mem_ctx
, ldb_get_config_basedn(ldb
));
1166 if (!ldb_dn_add_child_fmt(new_dn
,
1167 "CN=Directory Service,CN=Windows NT,CN=Services")) {
1168 talloc_free(new_dn
);
1171 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
,
1174 DSDB_FLAG_NEXT_MODULE
);
1175 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1176 talloc_free(new_dn
);
1177 return ldb_msg_find_ldb_val(res
->msgs
[0],
1180 talloc_free(new_dn
);
1184 bool dsdb_block_anonymous_ops(struct ldb_module
*module
,
1185 TALLOC_CTX
*mem_ctx
)
1187 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
1189 const struct ldb_val
*hr_val
= dsdb_module_find_dsheuristics(module
,
1191 if (hr_val
== NULL
|| hr_val
->length
< DS_HR_BLOCK_ANONYMOUS_OPS
) {
1193 } else if (hr_val
->data
[DS_HR_BLOCK_ANONYMOUS_OPS
-1] == '2') {
1199 talloc_free(tmp_ctx
);
1204 show the chain of requests, useful for debugging async requests
1206 void dsdb_req_chain_debug(struct ldb_request
*req
, int level
)
1211 while (req
&& req
->handle
) {
1212 DEBUG(level
,("req[%u] %p : %s\n", i
++, req
, ldb_req_location(req
)));
1213 req
= req
->handle
->parent
;