2 Unix SMB/CIFS implementation.
4 Extract the user/system database from a remote server
6 Copyright (C) Stefan Metzmacher 2004-2006
7 Copyright (C) Brad Henry 2005
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "libnet/libnet.h"
27 #include "lib/events/events.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/dlinklist.h"
31 #include <ldb_errors.h>
32 #include "librpc/ndr/libndr.h"
33 #include "librpc/gen_ndr/ndr_drsuapi.h"
34 #include "librpc/gen_ndr/ndr_drsblobs.h"
35 #include "librpc/gen_ndr/ndr_misc.h"
36 #include "system/time.h"
38 #include "auth/auth.h"
39 #include "auth/credentials/credentials.h"
40 #include "param/param.h"
41 #include "param/provision.h"
42 #include "libcli/security/security.h"
43 #include "dsdb/common/util.h"
46 #define DBGC_CLASS DBGC_DRS_REPL
49 List of tasks vampire.py must perform:
51 - but don't write the secrets.ldb
52 - results for this should be enough to handle the provision
53 - if vampire method is samsync
54 - Provision using these results
55 - do we still want to support this NT4 technology?
56 - Start samsync with libnet code
57 - provision in the callback
58 - Write out the secrets database, using the code from libnet_Join
61 struct libnet_vampire_cb_state
{
62 const char *netbios_name
;
63 const char *domain_name
;
65 struct cli_credentials
*machine_account
;
67 /* Schema loaded from local LDIF files */
68 struct dsdb_schema
*provision_schema
;
70 /* 1st pass, with some OIDs/attribute names/class names not
71 * converted, because we may not know them yet */
72 struct dsdb_schema
*self_made_schema
;
74 /* prefixMap in LDB format, from the remote DRS server */
75 DATA_BLOB prefixmap_blob
;
76 const struct dsdb_schema
*schema
;
78 struct ldb_context
*ldb
;
81 uint32_t object_count
;
82 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
83 struct drsuapi_DsReplicaObjectListItemEx
*last_object
;
86 const char *targetdir
;
88 struct loadparm_context
*lp_ctx
;
89 struct tevent_context
*event_ctx
;
90 unsigned total_objects
;
93 const char *server_dn_str
;
96 /* initialise a state structure ready for replication of chunks */
97 void *libnet_vampire_replicate_init(TALLOC_CTX
*mem_ctx
,
98 struct ldb_context
*samdb
,
99 struct loadparm_context
*lp_ctx
)
101 struct libnet_vampire_cb_state
*s
= talloc_zero(mem_ctx
, struct libnet_vampire_cb_state
);
108 s
->provision_schema
= dsdb_get_schema(s
->ldb
, s
);
109 s
->schema
= s
->provision_schema
;
110 s
->netbios_name
= lpcfg_netbios_name(lp_ctx
);
111 s
->domain_name
= lpcfg_workgroup(lp_ctx
);
112 s
->realm
= lpcfg_realm(lp_ctx
);
117 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
118 void *libnet_vampire_cb_state_init(TALLOC_CTX
*mem_ctx
,
119 struct loadparm_context
*lp_ctx
, struct tevent_context
*event_ctx
,
120 const char *netbios_name
, const char *domain_name
, const char *realm
,
121 const char *targetdir
)
123 struct libnet_vampire_cb_state
*s
= talloc_zero(mem_ctx
, struct libnet_vampire_cb_state
);
129 s
->event_ctx
= event_ctx
;
130 s
->netbios_name
= netbios_name
;
131 s
->domain_name
= domain_name
;
133 s
->targetdir
= targetdir
;
137 struct ldb_context
*libnet_vampire_cb_ldb(struct libnet_vampire_cb_state
*state
)
139 state
= talloc_get_type_abort(state
, struct libnet_vampire_cb_state
);
143 struct loadparm_context
*libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state
*state
)
145 state
= talloc_get_type_abort(state
, struct libnet_vampire_cb_state
);
146 return state
->lp_ctx
;
149 NTSTATUS
libnet_vampire_cb_prepare_db(void *private_data
,
150 const struct libnet_BecomeDC_PrepareDB
*p
)
152 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
153 struct provision_settings settings
;
154 struct provision_result result
;
157 ZERO_STRUCT(settings
);
158 settings
.site_name
= p
->dest_dsa
->site_name
;
159 settings
.root_dn_str
= p
->forest
->root_dn_str
;
160 settings
.domain_dn_str
= p
->domain
->dn_str
;
161 settings
.config_dn_str
= p
->forest
->config_dn_str
;
162 settings
.schema_dn_str
= p
->forest
->schema_dn_str
;
163 settings
.netbios_name
= p
->dest_dsa
->netbios_name
;
164 settings
.realm
= s
->realm
;
165 settings
.domain
= s
->domain_name
;
166 settings
.server_dn_str
= p
->dest_dsa
->server_dn_str
;
167 settings
.machine_password
= generate_random_machine_password(s
, 128, 255);
168 settings
.targetdir
= s
->targetdir
;
169 settings
.use_ntvfs
= true;
170 status
= provision_bare(s
, s
->lp_ctx
, &settings
, &result
);
172 if (!NT_STATUS_IS_OK(status
)) {
176 s
->ldb
= talloc_steal(s
, result
.samdb
);
177 s
->lp_ctx
= talloc_reparent(talloc_parent(result
.lp_ctx
), s
, result
.lp_ctx
);
178 s
->provision_schema
= dsdb_get_schema(s
->ldb
, s
);
179 s
->server_dn_str
= talloc_steal(s
, p
->dest_dsa
->server_dn_str
);
181 /* wrap the entire vapire operation in a transaction. This
182 isn't just cosmetic - we use this to ensure that linked
183 attribute back links are added at the end by relying on a
184 transaction commit hook in the linked attributes module. We
185 need to do this as the order of objects coming from the
186 server is not sufficiently deterministic to know that the
187 record that a backlink needs to be created in has itself
188 been created before the object containing the forward link
189 has come over the wire */
190 if (ldb_transaction_start(s
->ldb
) != LDB_SUCCESS
) {
191 return NT_STATUS_FOOBAR
;
199 NTSTATUS
libnet_vampire_cb_check_options(void *private_data
,
200 const struct libnet_BecomeDC_CheckOptions
*o
)
202 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
204 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
206 o
->domain
->netbios_name
, o
->domain
->dns_name
));
208 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
209 o
->source_dsa
->dns_name
, o
->source_dsa
->site_name
));
211 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
212 "\tschema object_version[%u]\n"
213 "\tdomain behavior_version[%u]\n"
214 "\tdomain w2k3_update_revision[%u]\n",
215 o
->forest
->crossref_behavior_version
,
216 o
->forest
->schema_object_version
,
217 o
->domain
->behavior_version
,
218 o
->domain
->w2k3_update_revision
));
223 static WERROR
libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state
*s
,
224 const struct libnet_BecomeDC_StoreChunk
*c
)
227 struct dsdb_schema_prefixmap
*pfm_remote
;
228 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
229 struct dsdb_schema
*provision_schema
;
230 uint32_t object_count
= 0;
231 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
232 uint32_t linked_attributes_count
;
233 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
234 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
;
235 struct dsdb_extended_replicated_objects
*schema_objs
;
236 struct repsFromTo1
*s_dsa
;
238 struct ldb_context
*schema_ldb
;
239 struct ldb_dn
*partition_dn
;
240 struct ldb_message
*msg
;
241 struct ldb_message_element
*prefixMap_el
;
245 uint64_t seq_num
= 0;
246 uint32_t cycle_before_switching
;
248 DEBUG(0,("Analyze and apply schema objects\n"));
250 s_dsa
= talloc_zero(s
, struct repsFromTo1
);
252 return WERR_NOT_ENOUGH_MEMORY
;
254 s_dsa
->other_info
= talloc(s_dsa
, struct repsFromTo1OtherInfo
);
255 if (s_dsa
->other_info
== NULL
) {
256 return WERR_NOT_ENOUGH_MEMORY
;
259 switch (c
->ctr_level
) {
261 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
262 object_count
= s
->schema_part
.object_count
;
263 first_object
= s
->schema_part
.first_object
;
264 linked_attributes_count
= 0;
265 linked_attributes
= NULL
;
266 s_dsa
->highwatermark
= c
->ctr1
->new_highwatermark
;
267 s_dsa
->source_dsa_obj_guid
= c
->ctr1
->source_dsa_guid
;
268 s_dsa
->source_dsa_invocation_id
= c
->ctr1
->source_dsa_invocation_id
;
269 uptodateness_vector
= NULL
; /* TODO: map it */
272 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
273 object_count
= s
->schema_part
.object_count
;
274 first_object
= s
->schema_part
.first_object
;
275 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
276 linked_attributes
= c
->ctr6
->linked_attributes
;
277 s_dsa
->highwatermark
= c
->ctr6
->new_highwatermark
;
278 s_dsa
->source_dsa_obj_guid
= c
->ctr6
->source_dsa_guid
;
279 s_dsa
->source_dsa_invocation_id
= c
->ctr6
->source_dsa_invocation_id
;
280 uptodateness_vector
= c
->ctr6
->uptodateness_vector
;
283 return WERR_INVALID_PARAMETER
;
285 /* We must set these up to ensure the replMetaData is written
286 * correctly, before our NTDS Settings entry is replicated */
287 ok
= samdb_set_ntds_invocation_id(s
->ldb
, &c
->dest_dsa
->invocation_id
);
289 DEBUG(0,("Failed to set cached ntds invocationId\n"));
290 return WERR_INTERNAL_ERROR
;
292 ok
= samdb_set_ntds_objectGUID(s
->ldb
, &c
->dest_dsa
->ntds_guid
);
294 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
295 return WERR_INTERNAL_ERROR
;
298 status
= dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr
, true,
299 s
, &pfm_remote
, NULL
);
300 if (!W_ERROR_IS_OK(status
)) {
301 DEBUG(0,(__location__
": Failed to decode remote prefixMap: %s",
302 win_errstr(status
)));
306 s_dsa
->replica_flags
= DRSUAPI_DRS_WRIT_REP
307 | DRSUAPI_DRS_INIT_SYNC
308 | DRSUAPI_DRS_PER_SYNC
;
309 memset(s_dsa
->schedule
, 0x11, sizeof(s_dsa
->schedule
));
311 tmp_dns_name
= GUID_string(s_dsa
->other_info
, &s_dsa
->source_dsa_obj_guid
);
312 if (tmp_dns_name
== NULL
) {
313 return WERR_NOT_ENOUGH_MEMORY
;
315 tmp_dns_name
= talloc_asprintf_append_buffer(tmp_dns_name
, "._msdcs.%s", c
->forest
->dns_name
);
316 if (tmp_dns_name
== NULL
) {
317 return WERR_NOT_ENOUGH_MEMORY
;
319 s_dsa
->other_info
->dns_name
= tmp_dns_name
;
321 if (s
->self_made_schema
== NULL
) {
322 DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
323 return WERR_INTERNAL_ERROR
;
326 schema_ldb
= provision_get_schema(s
, s
->lp_ctx
,
327 c
->forest
->schema_dn_str
,
330 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
331 "Will continue with local prefixMap\n"));
332 provision_schema
= dsdb_get_schema(s
->ldb
, s
);
334 provision_schema
= dsdb_get_schema(schema_ldb
, s
);
335 ret
= dsdb_reference_schema(s
->ldb
, provision_schema
, SCHEMA_MEMORY_ONLY
);
336 if (ret
!= LDB_SUCCESS
) {
337 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
338 return WERR_INTERNAL_ERROR
;
340 talloc_free(schema_ldb
);
343 cycle_before_switching
= lpcfg_parm_long(s
->lp_ctx
, NULL
,
345 "schema convert retrial", 1);
347 provision_schema
->resolving_in_progress
= true;
348 s
->self_made_schema
->resolving_in_progress
= true;
350 status
= dsdb_repl_resolve_working_schema(s
->ldb
,
352 cycle_before_switching
,
357 if (!W_ERROR_IS_OK(status
)) {
358 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
359 __location__
, win_errstr(status
)));
363 /* free temp objects for 1st conversion phase */
364 talloc_unlink(s
, provision_schema
);
366 s
->self_made_schema
->resolving_in_progress
= false;
369 * attach the schema we just brought over DRS to the ldb,
370 * so we can use it in dsdb_convert_object_ex below
372 ret
= dsdb_set_schema(s
->ldb
, s
->self_made_schema
, SCHEMA_WRITE
);
373 if (ret
!= LDB_SUCCESS
) {
374 DEBUG(0,("Failed to attach working schema from DRS.\n"));
375 return WERR_INTERNAL_ERROR
;
378 /* we don't want to access the self made schema anymore */
379 s
->schema
= s
->self_made_schema
;
380 s
->self_made_schema
= NULL
;
382 partition_dn
= ldb_dn_new(s
, s
->ldb
, c
->partition
->nc
.dn
);
383 if (partition_dn
== NULL
) {
384 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
385 return WERR_INVALID_PARAMETER
;
388 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
389 status
= dsdb_replicated_objects_convert(s
->ldb
,
395 linked_attributes_count
,
402 if (!W_ERROR_IS_OK(status
)) {
403 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status
)));
407 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
408 for (i
=0; i
< schema_objs
->num_objects
; i
++) {
409 struct ldb_ldif ldif
;
410 fprintf(stdout
, "#\n");
411 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
412 ldif
.msg
= schema_objs
->objects
[i
].msg
;
413 ldb_ldif_write_file(s
->ldb
, stdout
, &ldif
);
414 NDR_PRINT_DEBUG(replPropertyMetaDataBlob
, schema_objs
->objects
[i
].meta_data
);
418 status
= dsdb_replicated_objects_commit(s
->ldb
, NULL
, schema_objs
, &seq_num
);
419 if (!W_ERROR_IS_OK(status
)) {
420 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status
)));
424 msg
= ldb_msg_new(schema_objs
);
426 return WERR_NOT_ENOUGH_MEMORY
;
428 msg
->dn
= schema_objs
->partition_dn
;
430 /* We must ensure a prefixMap has been written. Unlike other
431 * attributes (including schemaInfo), it is not replicated in
432 * the normal replication stream. We can use the one from
433 * s->prefixmap_blob because we operate with one, unchanging
434 * prefixMap for this entire operation. */
435 ret
= ldb_msg_add_value(msg
, "prefixMap", &s
->prefixmap_blob
, &prefixMap_el
);
436 if (ret
!= LDB_SUCCESS
) {
437 return WERR_NOT_ENOUGH_MEMORY
;
439 /* We want to know if a prefixMap was written already, as it
440 * would mean that the above comment was not true, and we have
441 * somehow updated the prefixMap during this transaction */
442 prefixMap_el
->flags
= LDB_FLAG_MOD_ADD
;
444 ret
= dsdb_modify(s
->ldb
, msg
, DSDB_FLAG_AS_SYSTEM
);
445 if (ret
!= LDB_SUCCESS
) {
446 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s
->ldb
)));
447 return WERR_INTERNAL_ERROR
;
451 talloc_free(schema_objs
);
453 s
->schema
= dsdb_get_schema(s
->ldb
, s
);
455 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
456 return WERR_INTERNAL_ERROR
;
462 WERROR
libnet_vampire_cb_schema_chunk(void *private_data
,
463 const struct libnet_BecomeDC_StoreChunk
*c
)
465 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
467 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
468 uint32_t nc_object_count
;
469 uint32_t nc_total_received
= 0;
470 uint32_t object_count
;
471 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
472 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
473 uint32_t nc_linked_attributes_count
;
474 uint32_t linked_attributes_count
;
476 switch (c
->ctr_level
) {
478 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
479 nc_object_count
= c
->ctr1
->extended_ret
; /* maybe w2k send this unexpected? */
480 object_count
= c
->ctr1
->object_count
;
481 first_object
= c
->ctr1
->first_object
;
482 nc_linked_attributes_count
= 0;
483 linked_attributes_count
= 0;
486 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
487 nc_object_count
= c
->ctr6
->nc_object_count
;
488 object_count
= c
->ctr6
->object_count
;
489 first_object
= c
->ctr6
->first_object
;
490 nc_linked_attributes_count
= c
->ctr6
->nc_linked_attributes_count
;
491 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
494 return WERR_INVALID_PARAMETER
;
497 if (!s
->schema_part
.first_object
) {
498 nc_total_received
= object_count
;
500 nc_total_received
= s
->schema_part
.object_count
+ object_count
;
502 if (nc_object_count
) {
503 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
504 c
->partition
->nc
.dn
, nc_total_received
, nc_object_count
,
505 linked_attributes_count
, nc_linked_attributes_count
));
507 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
508 c
->partition
->nc
.dn
, nc_total_received
, linked_attributes_count
));
511 if (!s
->self_made_schema
) {
512 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info
;
513 /* Put the DRS prefixmap aside for the schema we are
514 * about to load in the provision, and into the one we
515 * are making with the help of DRS */
517 mapping_ctr_without_schema_info
= *mapping_ctr
;
519 /* This strips off the 0xFF schema info from the end,
520 * because we don't want it in the blob */
521 if (mapping_ctr_without_schema_info
.num_mappings
> 0) {
522 mapping_ctr_without_schema_info
.num_mappings
--;
524 werr
= dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info
, s
, &s
->prefixmap_blob
);
525 if (!W_ERROR_IS_OK(werr
)) {
529 /* Set up two manually-constructed schema - the local
530 * schema from the provision will be used to build
531 * one, which will then in turn be used to build the
533 s
->self_made_schema
= dsdb_new_schema(s
);
534 if (s
->self_made_schema
== NULL
) {
535 return WERR_NOT_ENOUGH_MEMORY
;
538 werr
= dsdb_load_prefixmap_from_drsuapi(s
->self_made_schema
, mapping_ctr
);
539 if (!W_ERROR_IS_OK(werr
)) {
543 werr
= dsdb_schema_pfm_contains_drsuapi_pfm(s
->self_made_schema
->prefixmap
, mapping_ctr
);
544 if (!W_ERROR_IS_OK(werr
)) {
549 if (!s
->schema_part
.first_object
) {
550 s
->schema_part
.object_count
= object_count
;
551 s
->schema_part
.first_object
= talloc_steal(s
, first_object
);
553 s
->schema_part
.object_count
+= object_count
;
554 s
->schema_part
.last_object
->next_object
= talloc_steal(s
->schema_part
.last_object
,
557 for (cur
= first_object
; cur
->next_object
; cur
= cur
->next_object
) {}
558 s
->schema_part
.last_object
= cur
;
560 if (!c
->partition
->more_data
) {
561 return libnet_vampire_cb_apply_schema(s
, c
);
567 WERROR
libnet_vampire_cb_store_chunk(void *private_data
,
568 const struct libnet_BecomeDC_StoreChunk
*c
)
570 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
572 struct dsdb_schema
*schema
;
573 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
574 uint32_t nc_object_count
;
575 uint32_t object_count
;
576 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
577 uint32_t nc_linked_attributes_count
;
578 uint32_t linked_attributes_count
;
579 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
580 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
;
581 struct dsdb_extended_replicated_objects
*objs
;
582 uint32_t req_replica_flags
;
583 uint32_t dsdb_repl_flags
= 0;
584 struct repsFromTo1
*s_dsa
;
588 bool is_exop
= false;
589 struct ldb_dn
*partition_dn
= NULL
;
590 struct ldb_dn
*nc_root
= NULL
;
592 s_dsa
= talloc_zero(s
, struct repsFromTo1
);
594 return WERR_NOT_ENOUGH_MEMORY
;
596 s_dsa
->other_info
= talloc(s_dsa
, struct repsFromTo1OtherInfo
);
597 if (s_dsa
->other_info
== NULL
) {
598 return WERR_NOT_ENOUGH_MEMORY
;
601 switch (c
->ctr_level
) {
603 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
604 nc_object_count
= c
->ctr1
->extended_ret
; /* maybe w2k send this unexpected? */
605 object_count
= c
->ctr1
->object_count
;
606 first_object
= c
->ctr1
->first_object
;
607 nc_linked_attributes_count
= 0;
608 linked_attributes_count
= 0;
609 linked_attributes
= NULL
;
610 s_dsa
->highwatermark
= c
->ctr1
->new_highwatermark
;
611 s_dsa
->source_dsa_obj_guid
= c
->ctr1
->source_dsa_guid
;
612 s_dsa
->source_dsa_invocation_id
= c
->ctr1
->source_dsa_invocation_id
;
613 uptodateness_vector
= NULL
; /* TODO: map it */
616 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
617 nc_object_count
= c
->ctr6
->nc_object_count
;
618 object_count
= c
->ctr6
->object_count
;
619 first_object
= c
->ctr6
->first_object
;
620 nc_linked_attributes_count
= c
->ctr6
->nc_linked_attributes_count
;
621 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
622 linked_attributes
= c
->ctr6
->linked_attributes
;
623 s_dsa
->highwatermark
= c
->ctr6
->new_highwatermark
;
624 s_dsa
->source_dsa_obj_guid
= c
->ctr6
->source_dsa_guid
;
625 s_dsa
->source_dsa_invocation_id
= c
->ctr6
->source_dsa_invocation_id
;
626 uptodateness_vector
= c
->ctr6
->uptodateness_vector
;
629 return WERR_INVALID_PARAMETER
;
632 switch (c
->req_level
) {
635 req_replica_flags
= 0;
638 if (c
->req5
->extended_op
!= DRSUAPI_EXOP_NONE
) {
641 req_replica_flags
= c
->req5
->replica_flags
;
644 if (c
->req8
->extended_op
!= DRSUAPI_EXOP_NONE
) {
647 req_replica_flags
= c
->req8
->replica_flags
;
650 if (c
->req10
->extended_op
!= DRSUAPI_EXOP_NONE
) {
653 req_replica_flags
= c
->req10
->replica_flags
;
655 if (c
->req10
->more_flags
& DRSUAPI_DRS_GET_TGT
) {
656 dsdb_repl_flags
|= DSDB_REPL_FLAG_TARGETS_UPTODATE
;
660 return WERR_INVALID_PARAMETER
;
663 if (req_replica_flags
& DRSUAPI_DRS_CRITICAL_ONLY
|| is_exop
) {
665 * If we only replicate the critical objects, or this
666 * is an exop we should not remember what we already
667 * got, as it is incomplete.
669 ZERO_STRUCT(s_dsa
->highwatermark
);
670 uptodateness_vector
= NULL
;
671 dsdb_repl_flags
|= DSDB_REPL_FLAG_OBJECT_SUBSET
;
674 /* TODO: avoid hardcoded flags */
675 s_dsa
->replica_flags
= DRSUAPI_DRS_WRIT_REP
676 | DRSUAPI_DRS_INIT_SYNC
677 | DRSUAPI_DRS_PER_SYNC
;
678 memset(s_dsa
->schedule
, 0x11, sizeof(s_dsa
->schedule
));
680 tmp_dns_name
= GUID_string(s_dsa
->other_info
, &s_dsa
->source_dsa_obj_guid
);
681 if (tmp_dns_name
== NULL
) {
682 return WERR_NOT_ENOUGH_MEMORY
;
684 tmp_dns_name
= talloc_asprintf_append_buffer(tmp_dns_name
, "._msdcs.%s", c
->forest
->dns_name
);
685 if (tmp_dns_name
== NULL
) {
686 return WERR_NOT_ENOUGH_MEMORY
;
688 s_dsa
->other_info
->dns_name
= tmp_dns_name
;
690 /* we want to show a count per partition */
691 if (!s
->last_partition
|| strcmp(s
->last_partition
, c
->partition
->nc
.dn
) != 0) {
692 s
->total_objects
= 0;
694 talloc_free(s
->last_partition
);
695 s
->last_partition
= talloc_strdup(s
, c
->partition
->nc
.dn
);
697 s
->total_objects
+= object_count
;
698 s
->total_links
+= linked_attributes_count
;
700 partition_dn
= ldb_dn_new(s_dsa
, s
->ldb
, c
->partition
->nc
.dn
);
701 if (partition_dn
== NULL
) {
702 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
703 return WERR_INVALID_PARAMETER
;
708 if (nc_object_count
) {
709 DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
710 c
->partition
->nc
.dn
, s
->total_objects
, nc_object_count
,
711 s
->total_links
, nc_linked_attributes_count
));
713 DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
714 c
->partition
->nc
.dn
, s
->total_objects
, linked_attributes_count
));
716 ret
= dsdb_find_nc_root(s
->ldb
, s_dsa
,
717 partition_dn
, &nc_root
);
718 if (ret
!= LDB_SUCCESS
) {
719 DEBUG(0,(__location__
": Failed to find nc_root for %s\n",
720 ldb_dn_get_linearized(partition_dn
)));
721 return WERR_INTERNAL_ERROR
;
724 if (nc_object_count
) {
725 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
726 c
->partition
->nc
.dn
, s
->total_objects
, nc_object_count
,
727 s
->total_links
, nc_linked_attributes_count
));
729 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
730 c
->partition
->nc
.dn
, s
->total_objects
, s
->total_links
));
732 nc_root
= partition_dn
;
736 schema
= dsdb_get_schema(s
->ldb
, NULL
);
738 DEBUG(0,(__location__
": Schema is not loaded yet!\n"));
739 return WERR_INTERNAL_ERROR
;
742 if (req_replica_flags
& DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
) {
743 dsdb_repl_flags
|= DSDB_REPL_FLAG_PRIORITISE_INCOMING
;
746 if (req_replica_flags
& DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING
) {
747 dsdb_repl_flags
|= DSDB_REPL_FLAG_EXPECT_NO_SECRETS
;
750 status
= dsdb_replicated_objects_convert(s
->ldb
,
756 linked_attributes_count
,
763 if (!W_ERROR_IS_OK(status
)) {
764 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status
)));
768 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
769 for (i
=0; i
< objs
->num_objects
; i
++) {
770 struct ldb_ldif ldif
;
771 fprintf(stdout
, "#\n");
772 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
773 ldif
.msg
= objs
->objects
[i
].msg
;
774 ldb_ldif_write_file(s
->ldb
, stdout
, &ldif
);
775 NDR_PRINT_DEBUG(replPropertyMetaDataBlob
, objs
->objects
[i
].meta_data
);
778 status
= dsdb_replicated_objects_commit(s
->ldb
, NULL
, objs
, &seq_num
);
779 if (!W_ERROR_IS_OK(status
)) {
780 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status
)));
784 /* reset debug counters once we've finished replicating the partition */
785 if (!c
->partition
->more_data
) {
786 s
->total_objects
= 0;
793 for (i
=0; i
< linked_attributes_count
; i
++) {
794 const struct dsdb_attribute
*sa
;
796 if (!linked_attributes
[i
].identifier
) {
797 DEBUG(0, ("No linked attribute identifier\n"));
798 return WERR_INTERNAL_ERROR
;
801 if (!linked_attributes
[i
].value
.blob
) {
802 DEBUG(0, ("No linked attribute value\n"));
803 return WERR_INTERNAL_ERROR
;
806 sa
= dsdb_attribute_by_attributeID_id(s
->schema
,
807 linked_attributes
[i
].attid
);
809 DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes
[i
].attid
));
810 return WERR_INTERNAL_ERROR
;
813 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
814 DEBUG(0,("# %s\n", sa
->lDAPDisplayName
));
815 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute
, &linked_attributes
[i
]);
817 linked_attributes
[i
].value
.blob
->data
,
818 linked_attributes
[i
].value
.blob
->length
);