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"
32 search for attrs on one DN, in the modules below
34 int dsdb_module_search_dn(struct ldb_module
*module
,
36 struct ldb_result
**_res
,
37 struct ldb_dn
*basedn
,
38 const char * const *attrs
,
42 struct ldb_request
*req
;
44 struct ldb_result
*res
;
46 tmp_ctx
= talloc_new(mem_ctx
);
48 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
51 return ldb_oom(ldb_module_get_ctx(module
));
54 ret
= ldb_build_search_req(&req
, ldb_module_get_ctx(module
), tmp_ctx
,
61 ldb_search_default_callback
,
63 if (ret
!= LDB_SUCCESS
) {
68 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
69 if (ret
!= LDB_SUCCESS
) {
74 /* Run the new request */
75 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
76 ret
= ldb_next_request(module
, req
);
77 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
78 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
80 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
81 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
82 ret
= ops
->modify(module
, req
);
84 if (ret
== LDB_SUCCESS
) {
85 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
88 if (ret
!= LDB_SUCCESS
) {
93 if (res
->count
!= 1) {
94 /* we may be reading a DB that does not have the 'check base on search' option... */
95 ret
= LDB_ERR_NO_SUCH_OBJECT
;
96 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
97 "dsdb_module_search_dn: did not find base dn %s (%d results)",
98 ldb_dn_get_linearized(basedn
), res
->count
);
100 *_res
= talloc_steal(mem_ctx
, res
);
102 talloc_free(tmp_ctx
);
107 search for attrs in the modules below
109 int dsdb_module_search(struct ldb_module
*module
,
111 struct ldb_result
**_res
,
112 struct ldb_dn
*basedn
, enum ldb_scope scope
,
113 const char * const *attrs
,
115 const char *format
, ...) _PRINTF_ATTRIBUTE(8, 9)
118 struct ldb_request
*req
;
120 struct ldb_result
*res
;
124 tmp_ctx
= talloc_new(mem_ctx
);
127 va_start(ap
, format
);
128 expression
= talloc_vasprintf(tmp_ctx
, format
, ap
);
132 talloc_free(tmp_ctx
);
133 return ldb_oom(ldb_module_get_ctx(module
));
139 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
141 talloc_free(tmp_ctx
);
142 return ldb_oom(ldb_module_get_ctx(module
));
145 ret
= ldb_build_search_req(&req
, ldb_module_get_ctx(module
), tmp_ctx
,
152 ldb_search_default_callback
,
154 if (ret
!= LDB_SUCCESS
) {
155 talloc_free(tmp_ctx
);
159 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
160 if (ret
!= LDB_SUCCESS
) {
161 talloc_free(tmp_ctx
);
165 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
166 ret
= ldb_next_request(module
, req
);
167 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
168 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
170 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
171 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
172 ret
= ops
->search(module
, req
);
174 if (ret
== LDB_SUCCESS
) {
175 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
179 if (ret
== LDB_SUCCESS
) {
180 *_res
= talloc_steal(mem_ctx
, res
);
182 talloc_free(tmp_ctx
);
187 find a DN given a GUID. This searches across all partitions
189 int dsdb_module_dn_by_guid(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
,
190 const struct GUID
*guid
, struct ldb_dn
**dn
)
192 struct ldb_result
*res
;
193 const char *attrs
[] = { NULL
};
194 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
197 ret
= dsdb_module_search(module
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
199 DSDB_FLAG_NEXT_MODULE
|
200 DSDB_SEARCH_SHOW_DELETED
|
201 DSDB_SEARCH_SEARCH_ALL_PARTITIONS
|
202 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
,
203 "objectGUID=%s", GUID_string(tmp_ctx
, guid
));
204 if (ret
!= LDB_SUCCESS
) {
205 talloc_free(tmp_ctx
);
208 if (res
->count
== 0) {
209 talloc_free(tmp_ctx
);
210 return LDB_ERR_NO_SUCH_OBJECT
;
212 if (res
->count
!= 1) {
213 ldb_asprintf_errstring(ldb_module_get_ctx(module
), "More than one object found matching objectGUID %s\n",
214 GUID_string(tmp_ctx
, guid
));
215 talloc_free(tmp_ctx
);
216 return LDB_ERR_OPERATIONS_ERROR
;
219 *dn
= talloc_steal(mem_ctx
, res
->msgs
[0]->dn
);
221 talloc_free(tmp_ctx
);
226 find a GUID given a DN.
228 int dsdb_module_guid_by_dn(struct ldb_module
*module
, struct ldb_dn
*dn
, struct GUID
*guid
)
230 const char *attrs
[] = { NULL
};
231 struct ldb_result
*res
;
232 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
236 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
, dn
, attrs
,
237 DSDB_FLAG_NEXT_MODULE
|
238 DSDB_SEARCH_SHOW_DELETED
|
239 DSDB_SEARCH_SHOW_EXTENDED_DN
);
240 if (ret
!= LDB_SUCCESS
) {
241 ldb_asprintf_errstring(ldb_module_get_ctx(module
), "Failed to find GUID for %s",
242 ldb_dn_get_linearized(dn
));
243 talloc_free(tmp_ctx
);
247 status
= dsdb_get_extended_dn_guid(res
->msgs
[0]->dn
, guid
, "GUID");
248 if (!NT_STATUS_IS_OK(status
)) {
249 talloc_free(tmp_ctx
);
250 return ldb_operr(ldb_module_get_ctx(module
));
253 talloc_free(tmp_ctx
);
258 a ldb_modify request operating on modules below the
261 int dsdb_module_modify(struct ldb_module
*module
,
262 const struct ldb_message
*message
,
265 struct ldb_request
*mod_req
;
267 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
268 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
269 struct ldb_result
*res
;
271 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
273 talloc_free(tmp_ctx
);
274 return ldb_oom(ldb_module_get_ctx(module
));
277 ret
= ldb_build_mod_req(&mod_req
, ldb
, tmp_ctx
,
281 ldb_modify_default_callback
,
283 if (ret
!= LDB_SUCCESS
) {
284 talloc_free(tmp_ctx
);
288 ret
= dsdb_request_add_controls(mod_req
, dsdb_flags
);
289 if (ret
!= LDB_SUCCESS
) {
290 talloc_free(tmp_ctx
);
294 /* Run the new request */
295 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
296 ret
= ldb_next_request(module
, mod_req
);
297 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
298 ret
= ldb_request(ldb_module_get_ctx(module
), mod_req
);
300 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
301 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
302 ret
= ops
->modify(module
, mod_req
);
304 if (ret
== LDB_SUCCESS
) {
305 ret
= ldb_wait(mod_req
->handle
, LDB_WAIT_ALL
);
308 talloc_free(tmp_ctx
);
315 a ldb_rename request operating on modules below the
318 int dsdb_module_rename(struct ldb_module
*module
,
319 struct ldb_dn
*olddn
, struct ldb_dn
*newdn
,
322 struct ldb_request
*req
;
324 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
325 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
326 struct ldb_result
*res
;
328 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
330 talloc_free(tmp_ctx
);
331 return ldb_oom(ldb_module_get_ctx(module
));
334 ret
= ldb_build_rename_req(&req
, ldb
, tmp_ctx
,
339 ldb_modify_default_callback
,
341 if (ret
!= LDB_SUCCESS
) {
342 talloc_free(tmp_ctx
);
346 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
347 if (ret
!= LDB_SUCCESS
) {
348 talloc_free(tmp_ctx
);
352 /* Run the new request */
353 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
354 ret
= ldb_next_request(module
, req
);
355 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
356 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
358 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
359 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
360 ret
= ops
->rename(module
, req
);
362 if (ret
== LDB_SUCCESS
) {
363 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
366 talloc_free(tmp_ctx
);
371 a ldb_add request operating on modules below the
374 int dsdb_module_add(struct ldb_module
*module
,
375 const struct ldb_message
*message
,
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
;
384 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
386 talloc_free(tmp_ctx
);
387 return ldb_oom(ldb_module_get_ctx(module
));
390 ret
= ldb_build_add_req(&req
, ldb
, tmp_ctx
,
394 ldb_modify_default_callback
,
396 if (ret
!= LDB_SUCCESS
) {
397 talloc_free(tmp_ctx
);
401 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
402 if (ret
!= LDB_SUCCESS
) {
403 talloc_free(tmp_ctx
);
407 /* Run the new request */
408 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
409 ret
= ldb_next_request(module
, req
);
410 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
411 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
413 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
414 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
415 ret
= ops
->add(module
, req
);
417 if (ret
== LDB_SUCCESS
) {
418 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
421 talloc_free(tmp_ctx
);
426 a ldb_delete request operating on modules below the
429 int dsdb_module_del(struct ldb_module
*module
,
433 struct ldb_request
*req
;
435 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
436 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
437 struct ldb_result
*res
;
439 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
441 talloc_free(tmp_ctx
);
445 ret
= ldb_build_del_req(&req
, ldb
, tmp_ctx
,
449 ldb_modify_default_callback
,
451 if (ret
!= LDB_SUCCESS
) {
452 talloc_free(tmp_ctx
);
456 ret
= dsdb_request_add_controls(req
, dsdb_flags
);
457 if (ret
!= LDB_SUCCESS
) {
458 talloc_free(tmp_ctx
);
462 /* Run the new request */
463 if (dsdb_flags
& DSDB_FLAG_NEXT_MODULE
) {
464 ret
= ldb_next_request(module
, req
);
465 } else if (dsdb_flags
& DSDB_FLAG_TOP_MODULE
) {
466 ret
= ldb_request(ldb_module_get_ctx(module
), req
);
468 const struct ldb_module_ops
*ops
= ldb_module_get_ops(module
);
469 SMB_ASSERT(dsdb_flags
& DSDB_FLAG_OWN_MODULE
);
470 ret
= ops
->del(module
, req
);
472 if (ret
== LDB_SUCCESS
) {
473 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
476 talloc_free(tmp_ctx
);
480 const struct dsdb_class
* get_last_structural_class(const struct dsdb_schema
*schema
,const struct ldb_message_element
*element
)
482 const struct dsdb_class
*last_class
= NULL
;
485 for (i
= 0; i
< element
->num_values
; i
++){
486 const struct dsdb_class
*tmp_class
= dsdb_class_by_lDAPDisplayName_ldb_val(schema
, &element
->values
[i
]);
488 if(tmp_class
== NULL
) {
492 if(tmp_class
->objectClassCategory
> 1) {
497 last_class
= tmp_class
;
499 if (tmp_class
->subClass_order
> last_class
->subClass_order
)
500 last_class
= tmp_class
;
508 check if a single valued link has multiple non-deleted values
510 This is needed when we will be using the RELAX control to stop
511 ldb_tdb from checking single valued links
513 int dsdb_check_single_valued_link(const struct dsdb_attribute
*attr
,
514 const struct ldb_message_element
*el
)
516 bool found_active
= false;
519 if (!(attr
->ldb_schema_attribute
->flags
& LDB_ATTR_FLAG_SINGLE_VALUE
) ||
520 el
->num_values
< 2) {
524 for (i
=0; i
<el
->num_values
; i
++) {
525 if (!dsdb_dn_is_deleted_val(&el
->values
[i
])) {
527 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
;
536 int dsdb_check_optional_feature(struct ldb_module
*module
, struct ldb_dn
*scope
,
537 struct GUID op_feature_guid
, bool *feature_enabled
)
540 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
541 struct ldb_result
*res
;
542 struct ldb_dn
*search_dn
;
543 struct GUID search_guid
;
544 const char *attrs
[] = {"msDS-EnabledFeature", NULL
};
547 struct ldb_message_element
*el
;
549 *feature_enabled
= false;
551 tmp_ctx
= talloc_new(ldb
);
553 ret
= ldb_search(ldb
, tmp_ctx
, &res
,
554 scope
, LDB_SCOPE_BASE
, attrs
,
556 if (ret
!= LDB_SUCCESS
) {
557 ldb_asprintf_errstring(ldb
,
558 "Could no find the scope object - dn: %s\n",
559 ldb_dn_get_linearized(scope
));
560 talloc_free(tmp_ctx
);
561 return LDB_ERR_OPERATIONS_ERROR
;
563 if (res
->msgs
[0]->num_elements
> 0) {
565 el
= ldb_msg_find_element(res
->msgs
[0],"msDS-EnabledFeature");
567 attrs
[0] = "msDS-OptionalFeatureGUID";
569 for (i
=0; i
<el
->num_values
; i
++) {
570 search_dn
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, &el
->values
[i
]);
572 ret
= ldb_search(ldb
, tmp_ctx
, &res
,
573 search_dn
, LDB_SCOPE_BASE
, attrs
,
575 if (ret
!= LDB_SUCCESS
) {
576 ldb_asprintf_errstring(ldb
,
577 "Could no find object dn: %s\n",
578 ldb_dn_get_linearized(search_dn
));
579 talloc_free(tmp_ctx
);
580 return LDB_ERR_OPERATIONS_ERROR
;
583 search_guid
= samdb_result_guid(res
->msgs
[0], "msDS-OptionalFeatureGUID");
585 if (GUID_compare(&search_guid
, &op_feature_guid
) == 0){
586 *feature_enabled
= true;
591 talloc_free(tmp_ctx
);
596 find a 'reference' DN that points at another object
597 (eg. serverReference, rIDManagerReference etc)
599 int dsdb_module_reference_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
*base
,
600 const char *attribute
, struct ldb_dn
**dn
)
602 const char *attrs
[2];
603 struct ldb_result
*res
;
606 attrs
[0] = attribute
;
609 ret
= dsdb_module_search_dn(module
, mem_ctx
, &res
, base
, attrs
,
610 DSDB_FLAG_NEXT_MODULE
);
611 if (ret
!= LDB_SUCCESS
) {
615 *dn
= ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module
),
616 mem_ctx
, res
->msgs
[0], attribute
);
619 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
627 find the RID Manager$ DN via the rIDManagerReference attribute in the
630 int dsdb_module_rid_manager_dn(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
, struct ldb_dn
**dn
)
632 return dsdb_module_reference_dn(module
, mem_ctx
,
633 ldb_get_default_basedn(ldb_module_get_ctx(module
)),
634 "rIDManagerReference", dn
);
639 update an integer attribute safely via a constrained delete/add
641 int dsdb_module_constrainted_update_integer(struct ldb_module
*module
, struct ldb_dn
*dn
,
642 const char *attr
, uint64_t old_val
, uint64_t new_val
)
644 struct ldb_message
*msg
;
645 struct ldb_message_element
*el
;
646 struct ldb_val v1
, v2
;
650 msg
= ldb_msg_new(module
);
653 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
654 if (ret
!= LDB_SUCCESS
) {
660 vstring
= talloc_asprintf(msg
, "%llu", (unsigned long long)old_val
);
663 return ldb_module_oom(module
);
665 v1
= data_blob_string_const(vstring
);
667 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
668 if (ret
!= LDB_SUCCESS
) {
674 vstring
= talloc_asprintf(msg
, "%llu", (unsigned long long)new_val
);
677 return ldb_module_oom(module
);
679 v2
= data_blob_string_const(vstring
);
681 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
687 used to chain to the callers callback
689 int dsdb_next_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
691 struct ldb_request
*up_req
= talloc_get_type(req
->context
, struct ldb_request
);
693 talloc_steal(up_req
, req
);
694 return up_req
->callback(up_req
, ares
);
699 set an integer attribute
701 int dsdb_module_set_integer(struct ldb_module
*module
, struct ldb_dn
*dn
,
702 const char *attr
, uint64_t new_val
)
704 struct ldb_message
*msg
;
707 msg
= ldb_msg_new(module
);
710 ret
= ldb_msg_add_fmt(msg
, attr
, "%llu", (unsigned long long)new_val
);
711 if (ret
!= LDB_SUCCESS
) {
715 msg
->elements
[0].flags
= LDB_FLAG_MOD_REPLACE
;
717 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
723 load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
724 object for a partition
726 int dsdb_module_load_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
727 uint64_t *uSN
, uint64_t *urgent_uSN
)
729 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
730 struct ldb_request
*req
;
732 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
733 struct dsdb_control_current_partition
*p_ctrl
;
734 struct ldb_result
*res
;
736 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
738 talloc_free(tmp_ctx
);
739 return ldb_module_oom(module
);
742 ret
= ldb_build_search_req(&req
, ldb
, tmp_ctx
,
743 ldb_dn_new(tmp_ctx
, ldb
, "@REPLCHANGED"),
747 res
, ldb_search_default_callback
,
749 if (ret
!= LDB_SUCCESS
) {
750 talloc_free(tmp_ctx
);
754 p_ctrl
= talloc(req
, struct dsdb_control_current_partition
);
755 if (p_ctrl
== NULL
) {
756 talloc_free(tmp_ctx
);
757 return ldb_module_oom(module
);
759 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
763 ret
= ldb_request_add_control(req
,
764 DSDB_CONTROL_CURRENT_PARTITION_OID
,
766 if (ret
!= LDB_SUCCESS
) {
767 talloc_free(tmp_ctx
);
771 /* Run the new request */
772 ret
= ldb_next_request(module
, req
);
774 if (ret
== LDB_SUCCESS
) {
775 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
778 if (ret
== LDB_ERR_NO_SUCH_OBJECT
|| ret
== LDB_ERR_INVALID_DN_SYNTAX
) {
779 /* it hasn't been created yet, which means
780 an implicit value of zero */
782 talloc_free(tmp_ctx
);
786 if (ret
!= LDB_SUCCESS
) {
787 talloc_free(tmp_ctx
);
791 if (res
->count
!= 1) {
797 *uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNHighest", 0);
799 *urgent_uSN
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "uSNUrgent", 0);
803 talloc_free(tmp_ctx
);
809 save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
812 int dsdb_module_save_partition_usn(struct ldb_module
*module
, struct ldb_dn
*dn
,
813 uint64_t uSN
, uint64_t urgent_uSN
)
815 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
816 struct ldb_request
*req
;
817 struct ldb_message
*msg
;
818 struct dsdb_control_current_partition
*p_ctrl
;
820 struct ldb_result
*res
;
822 msg
= ldb_msg_new(module
);
824 return ldb_module_oom(module
);
827 msg
->dn
= ldb_dn_new(msg
, ldb
, "@REPLCHANGED");
828 if (msg
->dn
== NULL
) {
830 return ldb_operr(ldb_module_get_ctx(module
));
833 res
= talloc_zero(msg
, struct ldb_result
);
836 return ldb_module_oom(module
);
839 ret
= ldb_msg_add_fmt(msg
, "uSNHighest", "%llu", (unsigned long long)uSN
);
840 if (ret
!= LDB_SUCCESS
) {
844 msg
->elements
[0].flags
= LDB_FLAG_MOD_REPLACE
;
846 /* urgent_uSN is optional so may not be stored */
848 ret
= ldb_msg_add_fmt(msg
, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN
);
849 if (ret
!= LDB_SUCCESS
) {
853 msg
->elements
[1].flags
= LDB_FLAG_MOD_REPLACE
;
857 p_ctrl
= talloc(msg
, struct dsdb_control_current_partition
);
858 if (p_ctrl
== NULL
) {
862 p_ctrl
->version
= DSDB_CONTROL_CURRENT_PARTITION_VERSION
;
864 ret
= ldb_build_mod_req(&req
, ldb
, msg
,
868 ldb_modify_default_callback
,
871 if (ret
!= LDB_SUCCESS
) {
876 ret
= ldb_request_add_control(req
,
877 DSDB_CONTROL_CURRENT_PARTITION_OID
,
879 if (ret
!= LDB_SUCCESS
) {
884 /* Run the new request */
885 ret
= ldb_next_request(module
, req
);
887 if (ret
== LDB_SUCCESS
) {
888 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
890 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
891 ret
= ldb_build_add_req(&req
, ldb
, msg
,
895 ldb_modify_default_callback
,
905 bool dsdb_module_am_system(struct ldb_module
*module
)
907 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
908 struct auth_session_info
*session_info
909 = (struct auth_session_info
*)ldb_get_opaque(ldb
, "sessionInfo");
910 return security_session_user_level(session_info
, NULL
) == SECURITY_SYSTEM
;
914 check if the recyclebin is enabled
916 int dsdb_recyclebin_enabled(struct ldb_module
*module
, bool *enabled
)
918 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
919 struct ldb_dn
*partitions_dn
;
920 struct GUID recyclebin_guid
;
923 partitions_dn
= samdb_partitions_dn(ldb
, module
);
925 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN
, &recyclebin_guid
);
927 ret
= dsdb_check_optional_feature(module
, partitions_dn
, recyclebin_guid
, enabled
);
928 if (ret
!= LDB_SUCCESS
) {
929 ldb_asprintf_errstring(ldb
, "Could not verify if Recycle Bin is enabled \n");
930 talloc_free(partitions_dn
);
931 return LDB_ERR_UNWILLING_TO_PERFORM
;
934 talloc_free(partitions_dn
);
938 bool is_attr_in_list(const char * const * attrs
, const char *attr
)
942 for (i
= 0; attrs
[i
]; i
++) {
943 if (ldb_attr_cmp(attrs
[i
], attr
) == 0)
950 int dsdb_msg_constrainted_update_int32(struct ldb_module
*module
,
951 struct ldb_message
*msg
,
953 const int32_t *old_val
,
954 const int32_t *new_val
)
956 struct ldb_message_element
*el
;
957 struct ldb_val
*v1
, *v2
;
962 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
963 if (ret
!= LDB_SUCCESS
) {
967 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
969 return ldb_module_oom(module
);
971 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*old_val
);
973 return ldb_module_oom(module
);
975 *el
->values
= data_blob_string_const(vstring
);
979 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
980 if (ret
!= LDB_SUCCESS
) {
984 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
986 return ldb_module_oom(module
);
988 vstring
= talloc_asprintf(el
->values
, "%ld", (long)*new_val
);
990 return ldb_module_oom(module
);
992 *el
->values
= data_blob_string_const(vstring
);
998 int dsdb_msg_constrainted_update_uint32(struct ldb_module
*module
,
999 struct ldb_message
*msg
,
1001 const uint32_t *old_val
,
1002 const uint32_t *new_val
)
1004 return dsdb_msg_constrainted_update_int32(module
, msg
, attr
,
1005 (const int32_t *)old_val
,
1006 (const int32_t *)new_val
);
1009 int dsdb_msg_constrainted_update_int64(struct ldb_module
*module
,
1010 struct ldb_message
*msg
,
1012 const int64_t *old_val
,
1013 const int64_t *new_val
)
1015 struct ldb_message_element
*el
;
1016 struct ldb_val
*v1
, *v2
;
1021 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_DELETE
, &el
);
1022 if (ret
!= LDB_SUCCESS
) {
1026 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1028 return ldb_module_oom(module
);
1030 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*old_val
);
1032 return ldb_module_oom(module
);
1034 *el
->values
= data_blob_string_const(vstring
);
1038 ret
= ldb_msg_add_empty(msg
, attr
, LDB_FLAG_MOD_ADD
, &el
);
1039 if (ret
!= LDB_SUCCESS
) {
1043 el
->values
= talloc_array(msg
, struct ldb_val
, el
->num_values
);
1045 return ldb_module_oom(module
);
1047 vstring
= talloc_asprintf(el
->values
, "%lld", (long long)*new_val
);
1049 return ldb_module_oom(module
);
1051 *el
->values
= data_blob_string_const(vstring
);
1057 int dsdb_msg_constrainted_update_uint64(struct ldb_module
*module
,
1058 struct ldb_message
*msg
,
1060 const uint64_t *old_val
,
1061 const uint64_t *new_val
)
1063 return dsdb_msg_constrainted_update_int64(module
, msg
, attr
,
1064 (const int64_t *)old_val
,
1065 (const int64_t *)new_val
);
1069 update an int32 attribute safely via a constrained delete/add
1071 int dsdb_module_constrainted_update_int32(struct ldb_module
*module
,
1074 const int32_t *old_val
,
1075 const int32_t *new_val
)
1077 struct ldb_message
*msg
;
1080 msg
= ldb_msg_new(module
);
1083 ret
= dsdb_msg_constrainted_update_int32(module
,
1087 if (ret
!= LDB_SUCCESS
) {
1092 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
1097 int dsdb_module_constrainted_update_uint32(struct ldb_module
*module
,
1100 const uint32_t *old_val
,
1101 const uint32_t *new_val
)
1103 return dsdb_module_constrainted_update_int32(module
, dn
, attr
,
1104 (const int32_t *)old_val
,
1105 (const int32_t *)new_val
);
1109 update an int64 attribute safely via a constrained delete/add
1111 int dsdb_module_constrainted_update_int64(struct ldb_module
*module
,
1114 const int64_t *old_val
,
1115 const int64_t *new_val
)
1117 struct ldb_message
*msg
;
1120 msg
= ldb_msg_new(module
);
1123 ret
= dsdb_msg_constrainted_update_int64(module
,
1127 if (ret
!= LDB_SUCCESS
) {
1132 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
1137 int dsdb_module_constrainted_update_uint64(struct ldb_module
*module
,
1140 const uint64_t *old_val
,
1141 const uint64_t *new_val
)
1143 return dsdb_module_constrainted_update_int64(module
, dn
, attr
,
1144 (const int64_t *)old_val
,
1145 (const int64_t *)new_val
);