2 Unix SMB/CIFS mplementation.
3 Helper functions for applying replicated objects
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "dsdb/samdb/samdb.h"
24 #include "lib/ldb/include/ldb_errors.h"
25 #include "../lib/util/dlinklist.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_drsuapi.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "../lib/crypto/crypto.h"
30 #include "../libcli/drsuapi/drsuapi.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "param/param.h"
35 * Multi-pass working schema creation
37 * - shallow copy initial schema supplied
38 * - create a working schema in multiple passes
39 * until all objects are resolved
40 * Working schema is a schema with Attributes, Classes
41 * and indexes, but w/o subClassOf, possibleSupperiors etc.
42 * It is to be used just us cache for converting attribute values.
44 WERROR
dsdb_repl_make_working_schema(struct ldb_context
*ldb
,
45 const struct dsdb_schema
*initial_schema
,
46 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
,
47 uint32_t object_count
,
48 const struct drsuapi_DsReplicaObjectListItemEx
*first_object
,
49 const DATA_BLOB
*gensec_skey
,
51 struct dsdb_schema
**_schema_out
)
54 struct schema_list
*next
, *prev
;
55 const struct drsuapi_DsReplicaObjectListItemEx
*obj
;
59 struct dsdb_schema_prefixmap
*pfm_remote
;
60 struct schema_list
*schema_list
= NULL
, *schema_list_item
, *schema_list_next_item
;
61 struct dsdb_schema
*working_schema
;
62 const struct drsuapi_DsReplicaObjectListItemEx
*cur
;
65 /* make a copy of the iniatial_scheam so we don't mess with it */
66 working_schema
= dsdb_schema_copy_shallow(mem_ctx
, ldb
, initial_schema
);
67 if (!working_schema
) {
68 DEBUG(0,(__location__
": schema copy failed!\n"));
72 /* we are going to need remote prefixMap for decoding */
73 werr
= dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr
, true,
74 mem_ctx
, &pfm_remote
, NULL
);
75 if (!W_ERROR_IS_OK(werr
)) {
76 DEBUG(0,(__location__
": Failed to decode remote prefixMap: %s",
81 /* create a list of objects yet to be converted */
82 for (cur
= first_object
; cur
; cur
= cur
->next_object
) {
83 schema_list_item
= talloc(mem_ctx
, struct schema_list
);
84 schema_list_item
->obj
= cur
;
85 DLIST_ADD_END(schema_list
, schema_list_item
, struct schema_list
);
88 /* resolve objects until all are resolved and in local schema */
92 uint32_t converted_obj_count
= 0;
93 uint32_t failed_obj_count
= 0;
94 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
95 W_ERROR_HAVE_NO_MEMORY(tmp_ctx
);
97 for (schema_list_item
= schema_list
; schema_list_item
; schema_list_item
=schema_list_next_item
) {
98 struct dsdb_extended_replicated_object object
;
100 cur
= schema_list_item
->obj
;
102 /* Save the next item, now we have saved out
103 * the current one, so we can DLIST_REMOVE it
105 schema_list_next_item
= schema_list_item
->next
;
108 * Convert the objects into LDB messages using the
109 * schema we have so far. It's ok if we fail to convert
110 * an object. We should convert more objects on next pass.
112 werr
= dsdb_convert_object_ex(ldb
, working_schema
, pfm_remote
,
115 if (!W_ERROR_IS_OK(werr
)) {
116 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n",
117 cur
->object
.identifier
->dn
));
122 * Convert the schema from ldb_message format
123 * (OIDs as OID strings) into schema, using
124 * the remote prefixMap
126 werr
= dsdb_schema_set_el_from_ldb_msg(ldb
,
129 if (!W_ERROR_IS_OK(werr
)) {
130 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
131 ldb_dn_get_linearized(object
.msg
->dn
),
135 DLIST_REMOVE(schema_list
, schema_list_item
);
136 talloc_free(schema_list_item
);
137 converted_obj_count
++;
141 talloc_free(tmp_ctx
);
143 DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n",
144 pass_no
, failed_obj_count
, converted_obj_count
, object_count
));
147 /* check if we converted any objects in this pass */
148 if (converted_obj_count
== 0) {
149 DEBUG(0,("Can't continue Schema load: didn't manage to convert any objects: all %d remaining of %d objects failed to convert\n", failed_obj_count
, object_count
));
150 return WERR_INTERNAL_ERROR
;
153 /* rebuild indexes */
154 ret
= dsdb_setup_sorted_accessors(ldb
, working_schema
);
155 if (LDB_SUCCESS
!= ret
) {
156 DEBUG(0,("Failed to create schema-cache indexes!\n"));
157 return WERR_INTERNAL_ERROR
;
161 *_schema_out
= working_schema
;
166 WERROR
dsdb_convert_object_ex(struct ldb_context
*ldb
,
167 const struct dsdb_schema
*schema
,
168 const struct dsdb_schema_prefixmap
*pfm_remote
,
169 const struct drsuapi_DsReplicaObjectListItemEx
*in
,
170 const DATA_BLOB
*gensec_skey
,
172 struct dsdb_extended_replicated_object
*out
)
177 struct ldb_message
*msg
;
178 struct replPropertyMetaDataBlob
*md
;
179 struct ldb_val guid_value
;
180 NTTIME whenChanged
= 0;
181 time_t whenChanged_t
;
182 const char *whenChanged_s
;
183 const char *rdn_name
= NULL
;
184 const struct ldb_val
*rdn_value
= NULL
;
185 const struct dsdb_attribute
*rdn_attr
= NULL
;
187 struct drsuapi_DsReplicaAttribute
*name_a
= NULL
;
188 struct drsuapi_DsReplicaMetaData
*name_d
= NULL
;
189 struct replPropertyMetaData1
*rdn_m
= NULL
;
190 struct dom_sid
*sid
= NULL
;
194 if (!in
->object
.identifier
) {
198 if (!in
->object
.identifier
->dn
|| !in
->object
.identifier
->dn
[0]) {
202 if (in
->object
.attribute_ctr
.num_attributes
!= 0 && !in
->meta_data_ctr
) {
206 if (in
->object
.attribute_ctr
.num_attributes
!= in
->meta_data_ctr
->count
) {
210 sid
= &in
->object
.identifier
->sid
;
211 if (sid
->num_auths
> 0) {
212 rid
= sid
->sub_auths
[sid
->num_auths
- 1];
215 msg
= ldb_msg_new(mem_ctx
);
216 W_ERROR_HAVE_NO_MEMORY(msg
);
218 msg
->dn
= ldb_dn_new(msg
, ldb
, in
->object
.identifier
->dn
);
219 W_ERROR_HAVE_NO_MEMORY(msg
->dn
);
221 rdn_name
= ldb_dn_get_rdn_name(msg
->dn
);
222 rdn_attr
= dsdb_attribute_by_lDAPDisplayName(schema
, rdn_name
);
226 rdn_attid
= rdn_attr
->attributeID_id
;
227 rdn_value
= ldb_dn_get_rdn_val(msg
->dn
);
229 msg
->num_elements
= in
->object
.attribute_ctr
.num_attributes
;
230 msg
->elements
= talloc_array(msg
, struct ldb_message_element
,
232 W_ERROR_HAVE_NO_MEMORY(msg
->elements
);
234 md
= talloc(mem_ctx
, struct replPropertyMetaDataBlob
);
235 W_ERROR_HAVE_NO_MEMORY(md
);
239 md
->ctr
.ctr1
.count
= in
->meta_data_ctr
->count
;
240 md
->ctr
.ctr1
.reserved
= 0;
241 md
->ctr
.ctr1
.array
= talloc_array(mem_ctx
,
242 struct replPropertyMetaData1
,
243 md
->ctr
.ctr1
.count
+ 1); /* +1 because of the RDN attribute */
244 W_ERROR_HAVE_NO_MEMORY(md
->ctr
.ctr1
.array
);
246 for (i
=0; i
< in
->meta_data_ctr
->count
; i
++) {
247 struct drsuapi_DsReplicaAttribute
*a
;
248 struct drsuapi_DsReplicaMetaData
*d
;
249 struct replPropertyMetaData1
*m
;
250 struct ldb_message_element
*e
;
253 a
= &in
->object
.attribute_ctr
.attributes
[i
];
254 d
= &in
->meta_data_ctr
->meta_data
[i
];
255 m
= &md
->ctr
.ctr1
.array
[i
];
256 e
= &msg
->elements
[i
];
258 for (j
=0; j
<a
->value_ctr
.num_values
; j
++) {
259 status
= drsuapi_decrypt_attribute(a
->value_ctr
.values
[j
].blob
, gensec_skey
, rid
, a
);
260 W_ERROR_NOT_OK_RETURN(status
);
263 status
= dsdb_attribute_drsuapi_to_ldb(ldb
, schema
, pfm_remote
,
264 a
, msg
->elements
, e
);
265 W_ERROR_NOT_OK_RETURN(status
);
268 m
->version
= d
->version
;
269 m
->originating_change_time
= d
->originating_change_time
;
270 m
->originating_invocation_id
= d
->originating_invocation_id
;
271 m
->originating_usn
= d
->originating_usn
;
274 if (d
->originating_change_time
> whenChanged
) {
275 whenChanged
= d
->originating_change_time
;
278 if (a
->attid
== DRSUAPI_ATTID_name
) {
281 rdn_m
= &md
->ctr
.ctr1
.array
[md
->ctr
.ctr1
.count
];
286 struct ldb_message_element
*el
;
287 el
= ldb_msg_find_element(msg
, rdn_attr
->lDAPDisplayName
);
289 ret
= ldb_msg_add_value(msg
, rdn_attr
->lDAPDisplayName
, rdn_value
, NULL
);
290 if (ret
!= LDB_SUCCESS
) {
294 if (el
->num_values
!= 1) {
295 DEBUG(0,(__location__
": Unexpected num_values=%u\n",
299 if (!ldb_val_equal_exact(&el
->values
[0], rdn_value
)) {
300 DEBUG(0,(__location__
": RDN value changed? '%*.*s' '%*.*s'\n",
301 (int)el
->values
[0].length
, (int)el
->values
[0].length
, el
->values
[0].data
,
302 (int)rdn_value
->length
, (int)rdn_value
->length
, rdn_value
->data
));
307 rdn_m
->attid
= rdn_attid
;
308 rdn_m
->version
= name_d
->version
;
309 rdn_m
->originating_change_time
= name_d
->originating_change_time
;
310 rdn_m
->originating_invocation_id
= name_d
->originating_invocation_id
;
311 rdn_m
->originating_usn
= name_d
->originating_usn
;
312 rdn_m
->local_usn
= 0;
313 md
->ctr
.ctr1
.count
++;
317 whenChanged_t
= nt_time_to_unix(whenChanged
);
318 whenChanged_s
= ldb_timestring(msg
, whenChanged_t
);
319 W_ERROR_HAVE_NO_MEMORY(whenChanged_s
);
321 nt_status
= GUID_to_ndr_blob(&in
->object
.identifier
->guid
, msg
, &guid_value
);
322 if (!NT_STATUS_IS_OK(nt_status
)) {
323 return ntstatus_to_werror(nt_status
);
327 out
->guid_value
= guid_value
;
328 out
->when_changed
= whenChanged_s
;
333 WERROR
dsdb_replicated_objects_convert(struct ldb_context
*ldb
,
334 const struct dsdb_schema
*schema
,
335 const char *partition_dn_str
,
336 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
,
337 uint32_t object_count
,
338 const struct drsuapi_DsReplicaObjectListItemEx
*first_object
,
339 uint32_t linked_attributes_count
,
340 const struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
,
341 const struct repsFromTo1
*source_dsa
,
342 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
,
343 const DATA_BLOB
*gensec_skey
,
345 struct dsdb_extended_replicated_objects
**objects
)
348 struct ldb_dn
*partition_dn
;
349 struct dsdb_schema_prefixmap
*pfm_remote
;
350 struct dsdb_extended_replicated_objects
*out
;
351 const struct drsuapi_DsReplicaObjectListItemEx
*cur
;
354 out
= talloc_zero(mem_ctx
, struct dsdb_extended_replicated_objects
);
355 W_ERROR_HAVE_NO_MEMORY(out
);
356 out
->version
= DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION
;
359 * Ensure schema is kept valid for as long as 'out'
360 * which may contain pointers to it
362 schema
= talloc_reference(out
, schema
);
363 W_ERROR_HAVE_NO_MEMORY(schema
);
365 partition_dn
= ldb_dn_new(out
, ldb
, partition_dn_str
);
366 W_ERROR_HAVE_NO_MEMORY_AND_FREE(partition_dn
, out
);
368 status
= dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr
, true,
369 out
, &pfm_remote
, NULL
);
370 if (!W_ERROR_IS_OK(status
)) {
371 DEBUG(0,(__location__
": Failed to decode remote prefixMap: %s",
372 win_errstr(status
)));
377 if (ldb_dn_compare(partition_dn
, ldb_get_schema_basedn(ldb
)) != 0) {
379 * check for schema changes in case
380 * we are not replicating Schema NC
382 status
= dsdb_schema_info_cmp(schema
, mapping_ctr
);
383 if (!W_ERROR_IS_OK(status
)) {
384 DEBUG(1,("Remote schema has changed while replicating %s\n",
391 out
->partition_dn
= partition_dn
;
393 out
->source_dsa
= source_dsa
;
394 out
->uptodateness_vector
= uptodateness_vector
;
396 out
->num_objects
= object_count
;
397 out
->objects
= talloc_array(out
,
398 struct dsdb_extended_replicated_object
,
400 W_ERROR_HAVE_NO_MEMORY_AND_FREE(out
->objects
, out
);
402 /* pass the linked attributes down to the repl_meta_data
404 out
->linked_attributes_count
= linked_attributes_count
;
405 out
->linked_attributes
= linked_attributes
;
407 for (i
=0, cur
= first_object
; cur
; cur
= cur
->next_object
, i
++) {
408 if (i
== out
->num_objects
) {
413 status
= dsdb_convert_object_ex(ldb
, schema
, pfm_remote
,
415 out
->objects
, &out
->objects
[i
]);
416 if (!W_ERROR_IS_OK(status
)) {
418 DEBUG(0,("Failed to convert object %s: %s\n",
419 cur
->object
.identifier
->dn
,
420 win_errstr(status
)));
424 if (i
!= out
->num_objects
) {
429 /* free pfm_remote, we won't need it anymore */
430 talloc_free(pfm_remote
);
437 * Commits a list of replicated objects.
439 * @param working_schema dsdb_schema to be used for resolving
440 * Classes/Attributes during Schema replication. If not NULL,
441 * it will be set on ldb and used while committing replicated objects
443 WERROR
dsdb_replicated_objects_commit(struct ldb_context
*ldb
,
444 struct dsdb_schema
*working_schema
,
445 struct dsdb_extended_replicated_objects
*objects
,
446 uint64_t *notify_uSN
)
448 struct ldb_result
*ext_res
;
449 struct dsdb_schema
*cur_schema
= NULL
;
451 uint64_t seq_num1
, seq_num2
;
453 /* TODO: handle linked attributes */
455 /* wrap the extended operation in a transaction
456 See [MS-DRSR] 3.3.2 Transactions
458 ret
= ldb_transaction_start(ldb
);
459 if (ret
!= LDB_SUCCESS
) {
460 DEBUG(0,(__location__
" Failed to start transaction\n"));
464 ret
= dsdb_load_partition_usn(ldb
, objects
->partition_dn
, &seq_num1
, NULL
);
465 if (ret
!= LDB_SUCCESS
) {
466 DEBUG(0,(__location__
" Failed to load partition uSN\n"));
467 ldb_transaction_cancel(ldb
);
472 * Set working_schema for ldb in case we are replicating from Schema NC.
473 * Schema won't be reloaded during Replicated Objects commit, as it is
474 * done in a transaction. So we need some way to search for newly
475 * added Classes and Attributes
477 if (working_schema
) {
478 /* store current schema so we can fall back in case of failure */
479 cur_schema
= dsdb_get_schema(ldb
, working_schema
);
481 ret
= dsdb_reference_schema(ldb
, working_schema
, false);
482 if (ret
!= LDB_SUCCESS
) {
483 DEBUG(0,(__location__
"Failed to reference working schema - %s\n",
485 /* TODO: Map LDB Error to NTSTATUS? */
486 ldb_transaction_cancel(ldb
);
487 return WERR_INTERNAL_ERROR
;
491 ret
= ldb_extended(ldb
, DSDB_EXTENDED_REPLICATED_OBJECTS_OID
, objects
, &ext_res
);
492 if (ret
!= LDB_SUCCESS
) {
493 /* restore previous schema */
495 dsdb_reference_schema(ldb
, cur_schema
, false);
496 dsdb_make_schema_global(ldb
, cur_schema
);
499 DEBUG(0,("Failed to apply records: %s: %s\n",
500 ldb_errstring(ldb
), ldb_strerror(ret
)));
501 ldb_transaction_cancel(ldb
);
504 talloc_free(ext_res
);
506 ret
= ldb_transaction_prepare_commit(ldb
);
507 if (ret
!= LDB_SUCCESS
) {
508 /* restore previous schema */
510 dsdb_reference_schema(ldb
, cur_schema
, false);
511 dsdb_make_schema_global(ldb
, cur_schema
);
513 DEBUG(0,(__location__
" Failed to prepare commit of transaction: %s\n",
514 ldb_errstring(ldb
)));
518 ret
= dsdb_load_partition_usn(ldb
, objects
->partition_dn
, &seq_num2
, NULL
);
519 if (ret
!= LDB_SUCCESS
) {
520 /* restore previous schema */
522 dsdb_reference_schema(ldb
, cur_schema
, false);
523 dsdb_make_schema_global(ldb
, cur_schema
);
525 DEBUG(0,(__location__
" Failed to load partition uSN\n"));
526 ldb_transaction_cancel(ldb
);
530 /* if this replication partner didn't need to be notified
531 before this transaction then it still doesn't need to be
532 notified, as the changes came from this server */
533 if (seq_num2
> seq_num1
&& seq_num1
<= *notify_uSN
) {
534 *notify_uSN
= seq_num2
;
537 ret
= ldb_transaction_commit(ldb
);
538 if (ret
!= LDB_SUCCESS
) {
539 /* restore previous schema */
541 dsdb_reference_schema(ldb
, cur_schema
, false);
542 dsdb_make_schema_global(ldb
, cur_schema
);
544 DEBUG(0,(__location__
" Failed to commit transaction\n"));
549 * Reset the Schema used by ldb. This will lead to
550 * a schema cache being refreshed from database.
552 if (working_schema
) {
553 cur_schema
= dsdb_get_schema(ldb
, NULL
);
554 /* TODO: What we do in case dsdb_get_schema() fail?
555 * We can't fallback at this point anymore */
557 dsdb_make_schema_global(ldb
, cur_schema
);
561 DEBUG(2,("Replicated %u objects (%u linked attributes) for %s\n",
562 objects
->num_objects
, objects
->linked_attributes_count
,
563 ldb_dn_get_linearized(objects
->partition_dn
)));
568 static WERROR
dsdb_origin_object_convert(struct ldb_context
*ldb
,
569 const struct dsdb_schema
*schema
,
570 const struct drsuapi_DsReplicaObjectListItem
*in
,
572 struct ldb_message
**_msg
)
576 struct ldb_message
*msg
;
578 if (!in
->object
.identifier
) {
582 if (!in
->object
.identifier
->dn
|| !in
->object
.identifier
->dn
[0]) {
586 msg
= ldb_msg_new(mem_ctx
);
587 W_ERROR_HAVE_NO_MEMORY(msg
);
589 msg
->dn
= ldb_dn_new(msg
, ldb
, in
->object
.identifier
->dn
);
590 W_ERROR_HAVE_NO_MEMORY(msg
->dn
);
592 msg
->num_elements
= in
->object
.attribute_ctr
.num_attributes
;
593 msg
->elements
= talloc_array(msg
, struct ldb_message_element
,
595 W_ERROR_HAVE_NO_MEMORY(msg
->elements
);
597 for (i
=0; i
< msg
->num_elements
; i
++) {
598 struct drsuapi_DsReplicaAttribute
*a
;
599 struct ldb_message_element
*e
;
601 a
= &in
->object
.attribute_ctr
.attributes
[i
];
602 e
= &msg
->elements
[i
];
604 status
= dsdb_attribute_drsuapi_to_ldb(ldb
, schema
, schema
->prefixmap
,
605 a
, msg
->elements
, e
);
606 W_ERROR_NOT_OK_RETURN(status
);
615 WERROR
dsdb_origin_objects_commit(struct ldb_context
*ldb
,
617 const struct drsuapi_DsReplicaObjectListItem
*first_object
,
619 struct drsuapi_DsReplicaObjectIdentifier2
**_ids
)
622 const struct dsdb_schema
*schema
;
623 const struct drsuapi_DsReplicaObjectListItem
*cur
;
624 struct ldb_message
**objects
;
625 struct drsuapi_DsReplicaObjectIdentifier2
*ids
;
627 uint32_t num_objects
= 0;
628 const char * const attrs
[] = {
633 struct ldb_result
*res
;
636 for (cur
= first_object
; cur
; cur
= cur
->next_object
) {
640 if (num_objects
== 0) {
644 ret
= ldb_transaction_start(ldb
);
645 if (ret
!= LDB_SUCCESS
) {
646 return WERR_DS_INTERNAL_FAILURE
;
649 objects
= talloc_array(mem_ctx
, struct ldb_message
*,
651 if (objects
== NULL
) {
656 schema
= dsdb_get_schema(ldb
, objects
);
658 return WERR_DS_SCHEMA_NOT_LOADED
;
661 for (i
=0, cur
= first_object
; cur
; cur
= cur
->next_object
, i
++) {
662 status
= dsdb_origin_object_convert(ldb
, schema
, cur
,
663 objects
, &objects
[i
]);
664 if (!W_ERROR_IS_OK(status
)) {
669 ids
= talloc_array(mem_ctx
,
670 struct drsuapi_DsReplicaObjectIdentifier2
,
677 for (i
=0; i
< num_objects
; i
++) {
678 struct dom_sid
*sid
= NULL
;
679 struct ldb_request
*add_req
;
681 DEBUG(6,(__location__
": adding %s\n",
682 ldb_dn_get_linearized(objects
[i
]->dn
)));
684 ret
= ldb_build_add_req(&add_req
,
690 ldb_op_default_callback
,
692 if (ret
!= LDB_SUCCESS
) {
693 status
= WERR_DS_INTERNAL_FAILURE
;
697 ret
= ldb_request_add_control(add_req
, LDB_CONTROL_RELAX_OID
, true, NULL
);
698 if (ret
!= LDB_SUCCESS
) {
699 status
= WERR_DS_INTERNAL_FAILURE
;
703 ret
= ldb_request(ldb
, add_req
);
704 if (ret
== LDB_SUCCESS
) {
705 ret
= ldb_wait(add_req
->handle
, LDB_WAIT_ALL
);
707 if (ret
!= LDB_SUCCESS
) {
708 DEBUG(0,(__location__
": Failed add of %s - %s\n",
709 ldb_dn_get_linearized(objects
[i
]->dn
), ldb_errstring(ldb
)));
710 status
= WERR_DS_INTERNAL_FAILURE
;
714 talloc_free(add_req
);
716 ret
= ldb_search(ldb
, objects
, &res
, objects
[i
]->dn
,
717 LDB_SCOPE_BASE
, attrs
,
719 if (ret
!= LDB_SUCCESS
) {
720 status
= WERR_DS_INTERNAL_FAILURE
;
723 ids
[i
].guid
= samdb_result_guid(res
->msgs
[0], "objectGUID");
724 sid
= samdb_result_dom_sid(objects
, res
->msgs
[0], "objectSid");
728 ZERO_STRUCT(ids
[i
].sid
);
732 ret
= ldb_transaction_commit(ldb
);
733 if (ret
!= LDB_SUCCESS
) {
734 return WERR_DS_INTERNAL_FAILURE
;
737 talloc_free(objects
);
744 talloc_free(objects
);
745 ldb_transaction_cancel(ldb
);