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 "libnet/libnet_join_proto.h"
28 #include "lib/events/events.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "../lib/util/dlinklist.h"
32 #include <ldb_errors.h>
33 #include "librpc/ndr/libndr.h"
34 #include "librpc/gen_ndr/ndr_drsuapi.h"
35 #include "librpc/gen_ndr/ndr_drsblobs.h"
36 #include "librpc/gen_ndr/ndr_misc.h"
37 #include "system/time.h"
39 #include "auth/auth.h"
40 #include "auth/credentials/credentials.h"
41 #include "param/param.h"
42 #include "param/provision.h"
43 #include "libcli/security/security.h"
44 #include "dsdb/common/util.h"
47 #define DBGC_CLASS DBGC_DRS_REPL
50 List of tasks vampire.py must perform:
52 - but don't write the secrets.ldb
53 - results for this should be enough to handle the provision
54 - if vampire method is samsync
55 - Provision using these results
56 - do we still want to support this NT4 technology?
57 - Start samsync with libnet code
58 - provision in the callback
59 - Write out the secrets database, using the code from libnet_Join
62 struct libnet_vampire_cb_state
{
63 const char *netbios_name
;
64 const char *domain_name
;
66 struct cli_credentials
*machine_account
;
68 /* Schema loaded from local LDIF files */
69 struct dsdb_schema
*provision_schema
;
71 /* 1st pass, with some OIDs/attribute names/class names not
72 * converted, because we may not know them yet */
73 struct dsdb_schema
*self_made_schema
;
75 /* prefixMap in LDB format, from the remote DRS server */
76 DATA_BLOB prefixmap_blob
;
77 const struct dsdb_schema
*schema
;
79 struct ldb_context
*ldb
;
82 uint32_t object_count
;
83 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
84 struct drsuapi_DsReplicaObjectListItemEx
*last_object
;
87 const char *targetdir
;
89 struct loadparm_context
*lp_ctx
;
90 struct tevent_context
*event_ctx
;
91 unsigned total_objects
;
94 const char *server_dn_str
;
97 /* initialise a state structure ready for replication of chunks */
98 void *libnet_vampire_replicate_init(TALLOC_CTX
*mem_ctx
,
99 struct ldb_context
*samdb
,
100 struct loadparm_context
*lp_ctx
)
102 struct libnet_vampire_cb_state
*s
= talloc_zero(mem_ctx
, struct libnet_vampire_cb_state
);
109 s
->provision_schema
= dsdb_get_schema(s
->ldb
, s
);
110 s
->schema
= s
->provision_schema
;
111 s
->netbios_name
= lpcfg_netbios_name(lp_ctx
);
112 s
->domain_name
= lpcfg_workgroup(lp_ctx
);
113 s
->realm
= lpcfg_realm(lp_ctx
);
118 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
119 void *libnet_vampire_cb_state_init(TALLOC_CTX
*mem_ctx
,
120 struct loadparm_context
*lp_ctx
, struct tevent_context
*event_ctx
,
121 const char *netbios_name
, const char *domain_name
, const char *realm
,
122 const char *targetdir
)
124 struct libnet_vampire_cb_state
*s
= talloc_zero(mem_ctx
, struct libnet_vampire_cb_state
);
130 s
->event_ctx
= event_ctx
;
131 s
->netbios_name
= netbios_name
;
132 s
->domain_name
= domain_name
;
134 s
->targetdir
= targetdir
;
138 struct ldb_context
*libnet_vampire_cb_ldb(struct libnet_vampire_cb_state
*state
)
140 state
= talloc_get_type_abort(state
, struct libnet_vampire_cb_state
);
144 struct loadparm_context
*libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state
*state
)
146 state
= talloc_get_type_abort(state
, struct libnet_vampire_cb_state
);
147 return state
->lp_ctx
;
150 NTSTATUS
libnet_vampire_cb_prepare_db(void *private_data
,
151 const struct libnet_BecomeDC_PrepareDB
*p
)
153 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
154 struct provision_settings settings
;
155 struct provision_result result
;
158 ZERO_STRUCT(settings
);
159 settings
.site_name
= p
->dest_dsa
->site_name
;
160 settings
.root_dn_str
= p
->forest
->root_dn_str
;
161 settings
.domain_dn_str
= p
->domain
->dn_str
;
162 settings
.config_dn_str
= p
->forest
->config_dn_str
;
163 settings
.schema_dn_str
= p
->forest
->schema_dn_str
;
164 settings
.netbios_name
= p
->dest_dsa
->netbios_name
;
165 settings
.realm
= s
->realm
;
166 settings
.domain
= s
->domain_name
;
167 settings
.server_dn_str
= p
->dest_dsa
->server_dn_str
;
168 settings
.machine_password
= generate_random_machine_password(s
, 120, 120);
169 settings
.targetdir
= s
->targetdir
;
170 settings
.use_ntvfs
= true;
171 status
= provision_bare(s
, s
->lp_ctx
, &settings
, &result
);
173 if (!NT_STATUS_IS_OK(status
)) {
177 s
->ldb
= talloc_steal(s
, result
.samdb
);
178 s
->lp_ctx
= talloc_reparent(talloc_parent(result
.lp_ctx
), s
, result
.lp_ctx
);
179 s
->provision_schema
= dsdb_get_schema(s
->ldb
, s
);
180 s
->server_dn_str
= talloc_steal(s
, p
->dest_dsa
->server_dn_str
);
182 /* wrap the entire vapire operation in a transaction. This
183 isn't just cosmetic - we use this to ensure that linked
184 attribute back links are added at the end by relying on a
185 transaction commit hook in the linked attributes module. We
186 need to do this as the order of objects coming from the
187 server is not sufficiently deterministic to know that the
188 record that a backlink needs to be created in has itself
189 been created before the object containing the forward link
190 has come over the wire */
191 if (ldb_transaction_start(s
->ldb
) != LDB_SUCCESS
) {
192 return NT_STATUS_FOOBAR
;
200 NTSTATUS
libnet_vampire_cb_check_options(void *private_data
,
201 const struct libnet_BecomeDC_CheckOptions
*o
)
203 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
205 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
207 o
->domain
->netbios_name
, o
->domain
->dns_name
));
209 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
210 o
->source_dsa
->dns_name
, o
->source_dsa
->site_name
));
212 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
213 "\tschema object_version[%u]\n"
214 "\tdomain behavior_version[%u]\n"
215 "\tdomain w2k3_update_revision[%u]\n",
216 o
->forest
->crossref_behavior_version
,
217 o
->forest
->schema_object_version
,
218 o
->domain
->behavior_version
,
219 o
->domain
->w2k3_update_revision
));
224 static WERROR
libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state
*s
,
225 const struct libnet_BecomeDC_StoreChunk
*c
)
228 struct dsdb_schema_prefixmap
*pfm_remote
;
229 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
230 struct dsdb_schema
*provision_schema
;
231 uint32_t object_count
= 0;
232 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
233 uint32_t linked_attributes_count
;
234 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
235 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
;
236 struct dsdb_extended_replicated_objects
*schema_objs
;
237 struct repsFromTo1
*s_dsa
;
239 struct ldb_context
*schema_ldb
;
240 struct ldb_dn
*partition_dn
;
241 struct ldb_message
*msg
;
242 struct ldb_message_element
*prefixMap_el
;
246 uint64_t seq_num
= 0;
247 uint32_t cycle_before_switching
;
249 DEBUG(0,("Analyze and apply schema objects\n"));
251 s_dsa
= talloc_zero(s
, struct repsFromTo1
);
253 return WERR_NOT_ENOUGH_MEMORY
;
255 s_dsa
->other_info
= talloc(s_dsa
, struct repsFromTo1OtherInfo
);
256 if (s_dsa
->other_info
== NULL
) {
257 return WERR_NOT_ENOUGH_MEMORY
;
260 switch (c
->ctr_level
) {
262 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
263 object_count
= s
->schema_part
.object_count
;
264 first_object
= s
->schema_part
.first_object
;
265 linked_attributes_count
= 0;
266 linked_attributes
= NULL
;
267 s_dsa
->highwatermark
= c
->ctr1
->new_highwatermark
;
268 s_dsa
->source_dsa_obj_guid
= c
->ctr1
->source_dsa_guid
;
269 s_dsa
->source_dsa_invocation_id
= c
->ctr1
->source_dsa_invocation_id
;
270 uptodateness_vector
= NULL
; /* TODO: map it */
273 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
274 object_count
= s
->schema_part
.object_count
;
275 first_object
= s
->schema_part
.first_object
;
276 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
277 linked_attributes
= c
->ctr6
->linked_attributes
;
278 s_dsa
->highwatermark
= c
->ctr6
->new_highwatermark
;
279 s_dsa
->source_dsa_obj_guid
= c
->ctr6
->source_dsa_guid
;
280 s_dsa
->source_dsa_invocation_id
= c
->ctr6
->source_dsa_invocation_id
;
281 uptodateness_vector
= c
->ctr6
->uptodateness_vector
;
284 return WERR_INVALID_PARAMETER
;
286 /* We must set these up to ensure the replMetaData is written
287 * correctly, before our NTDS Settings entry is replicated */
288 ok
= samdb_set_ntds_invocation_id(s
->ldb
, &c
->dest_dsa
->invocation_id
);
290 DEBUG(0,("Failed to set cached ntds invocationId\n"));
291 return WERR_INTERNAL_ERROR
;
293 ok
= samdb_set_ntds_objectGUID(s
->ldb
, &c
->dest_dsa
->ntds_guid
);
295 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
296 return WERR_INTERNAL_ERROR
;
299 status
= dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr
, true,
300 s
, &pfm_remote
, NULL
);
301 if (!W_ERROR_IS_OK(status
)) {
302 DEBUG(0,(__location__
": Failed to decode remote prefixMap: %s\n",
303 win_errstr(status
)));
307 s_dsa
->replica_flags
= DRSUAPI_DRS_WRIT_REP
308 | DRSUAPI_DRS_INIT_SYNC
309 | DRSUAPI_DRS_PER_SYNC
;
310 memset(s_dsa
->schedule
, 0x11, sizeof(s_dsa
->schedule
));
312 tmp_dns_name
= GUID_string(s_dsa
->other_info
, &s_dsa
->source_dsa_obj_guid
);
313 if (tmp_dns_name
== NULL
) {
314 return WERR_NOT_ENOUGH_MEMORY
;
316 tmp_dns_name
= talloc_asprintf_append_buffer(tmp_dns_name
, "._msdcs.%s", c
->forest
->dns_name
);
317 if (tmp_dns_name
== NULL
) {
318 return WERR_NOT_ENOUGH_MEMORY
;
320 s_dsa
->other_info
->dns_name
= tmp_dns_name
;
322 if (s
->self_made_schema
== NULL
) {
323 DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
324 return WERR_INTERNAL_ERROR
;
327 schema_ldb
= provision_get_schema(s
, s
->lp_ctx
,
328 c
->forest
->schema_dn_str
,
331 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
332 "Will continue with local prefixMap\n"));
333 provision_schema
= dsdb_get_schema(s
->ldb
, s
);
335 provision_schema
= dsdb_get_schema(schema_ldb
, s
);
336 ret
= dsdb_reference_schema(s
->ldb
, provision_schema
, SCHEMA_MEMORY_ONLY
);
337 if (ret
!= LDB_SUCCESS
) {
338 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap.\n"));
339 return WERR_INTERNAL_ERROR
;
341 talloc_unlink(s
, schema_ldb
);
344 cycle_before_switching
= lpcfg_parm_long(s
->lp_ctx
, NULL
,
346 "schema convert retrial", 1);
348 provision_schema
->resolving_in_progress
= true;
349 s
->self_made_schema
->resolving_in_progress
= true;
351 status
= dsdb_repl_resolve_working_schema(s
->ldb
,
353 cycle_before_switching
,
358 if (!W_ERROR_IS_OK(status
)) {
359 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s\n",
360 __location__
, win_errstr(status
)));
364 /* free temp objects for 1st conversion phase */
365 talloc_unlink(s
, provision_schema
);
367 s
->self_made_schema
->resolving_in_progress
= false;
370 * attach the schema we just brought over DRS to the ldb,
371 * so we can use it in dsdb_convert_object_ex below
373 ret
= dsdb_set_schema(s
->ldb
, s
->self_made_schema
, SCHEMA_WRITE
);
374 if (ret
!= LDB_SUCCESS
) {
375 DEBUG(0,("Failed to attach working schema from DRS.\n"));
376 return WERR_INTERNAL_ERROR
;
379 /* we don't want to access the self made schema anymore */
380 s
->schema
= s
->self_made_schema
;
381 s
->self_made_schema
= NULL
;
383 partition_dn
= ldb_dn_new(s
, s
->ldb
, c
->partition
->nc
.dn
);
384 if (partition_dn
== NULL
) {
385 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
386 return WERR_INVALID_PARAMETER
;
389 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
390 status
= dsdb_replicated_objects_convert(s
->ldb
,
396 linked_attributes_count
,
403 if (!W_ERROR_IS_OK(status
)) {
404 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status
)));
408 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
409 for (i
=0; i
< schema_objs
->num_objects
; i
++) {
410 struct ldb_ldif ldif
;
411 fprintf(stdout
, "#\n");
412 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
413 ldif
.msg
= schema_objs
->objects
[i
].msg
;
414 ldb_ldif_write_file(s
->ldb
, stdout
, &ldif
);
415 NDR_PRINT_DEBUG(replPropertyMetaDataBlob
, schema_objs
->objects
[i
].meta_data
);
419 status
= dsdb_replicated_objects_commit(s
->ldb
, NULL
, schema_objs
, &seq_num
);
420 if (!W_ERROR_IS_OK(status
)) {
421 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status
)));
425 msg
= ldb_msg_new(schema_objs
);
427 return WERR_NOT_ENOUGH_MEMORY
;
429 msg
->dn
= schema_objs
->partition_dn
;
431 /* We must ensure a prefixMap has been written. Unlike other
432 * attributes (including schemaInfo), it is not replicated in
433 * the normal replication stream. We can use the one from
434 * s->prefixmap_blob because we operate with one, unchanging
435 * prefixMap for this entire operation. */
436 ret
= ldb_msg_add_value(msg
, "prefixMap", &s
->prefixmap_blob
, &prefixMap_el
);
437 if (ret
!= LDB_SUCCESS
) {
438 return WERR_NOT_ENOUGH_MEMORY
;
440 /* We want to know if a prefixMap was written already, as it
441 * would mean that the above comment was not true, and we have
442 * somehow updated the prefixMap during this transaction */
443 prefixMap_el
->flags
= LDB_FLAG_MOD_ADD
;
445 ret
= dsdb_modify(s
->ldb
, msg
, DSDB_FLAG_AS_SYSTEM
);
446 if (ret
!= LDB_SUCCESS
) {
447 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s
->ldb
)));
448 return WERR_INTERNAL_ERROR
;
452 talloc_free(schema_objs
);
454 s
->schema
= dsdb_get_schema(s
->ldb
, s
);
456 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
457 return WERR_INTERNAL_ERROR
;
463 WERROR
libnet_vampire_cb_schema_chunk(void *private_data
,
464 const struct libnet_BecomeDC_StoreChunk
*c
)
466 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
468 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
469 uint32_t nc_object_count
;
470 uint32_t nc_total_received
= 0;
471 uint32_t object_count
;
472 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
473 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
474 uint32_t nc_linked_attributes_count
;
475 uint32_t linked_attributes_count
;
477 switch (c
->ctr_level
) {
479 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
480 nc_object_count
= c
->ctr1
->extended_ret
; /* maybe w2k send this unexpected? */
481 object_count
= c
->ctr1
->object_count
;
482 first_object
= c
->ctr1
->first_object
;
483 nc_linked_attributes_count
= 0;
484 linked_attributes_count
= 0;
487 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
488 nc_object_count
= c
->ctr6
->nc_object_count
;
489 object_count
= c
->ctr6
->object_count
;
490 first_object
= c
->ctr6
->first_object
;
491 nc_linked_attributes_count
= c
->ctr6
->nc_linked_attributes_count
;
492 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
495 return WERR_INVALID_PARAMETER
;
498 if (!s
->schema_part
.first_object
) {
499 nc_total_received
= object_count
;
501 nc_total_received
= s
->schema_part
.object_count
+ object_count
;
503 if (nc_object_count
) {
504 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
505 c
->partition
->nc
.dn
, nc_total_received
, nc_object_count
,
506 linked_attributes_count
, nc_linked_attributes_count
));
508 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
509 c
->partition
->nc
.dn
, nc_total_received
, linked_attributes_count
));
512 if (!s
->self_made_schema
) {
513 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info
;
514 /* Put the DRS prefixmap aside for the schema we are
515 * about to load in the provision, and into the one we
516 * are making with the help of DRS */
518 mapping_ctr_without_schema_info
= *mapping_ctr
;
520 /* This strips off the 0xFF schema info from the end,
521 * because we don't want it in the blob */
522 if (mapping_ctr_without_schema_info
.num_mappings
> 0) {
523 mapping_ctr_without_schema_info
.num_mappings
--;
525 werr
= dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info
, s
, &s
->prefixmap_blob
);
526 if (!W_ERROR_IS_OK(werr
)) {
530 /* Set up two manually-constructed schema - the local
531 * schema from the provision will be used to build
532 * one, which will then in turn be used to build the
534 s
->self_made_schema
= dsdb_new_schema(s
);
535 if (s
->self_made_schema
== NULL
) {
536 return WERR_NOT_ENOUGH_MEMORY
;
539 werr
= dsdb_load_prefixmap_from_drsuapi(s
->self_made_schema
, mapping_ctr
);
540 if (!W_ERROR_IS_OK(werr
)) {
544 werr
= dsdb_schema_pfm_contains_drsuapi_pfm(s
->self_made_schema
->prefixmap
, mapping_ctr
);
545 if (!W_ERROR_IS_OK(werr
)) {
550 if (!s
->schema_part
.first_object
) {
551 s
->schema_part
.object_count
= object_count
;
552 s
->schema_part
.first_object
= talloc_steal(s
, first_object
);
554 s
->schema_part
.object_count
+= object_count
;
555 s
->schema_part
.last_object
->next_object
= talloc_steal(s
->schema_part
.last_object
,
558 if (first_object
!= NULL
) {
559 for (cur
= first_object
; cur
->next_object
; cur
= cur
->next_object
) {}
564 s
->schema_part
.last_object
= cur
;
566 if (!c
->partition
->more_data
) {
567 return libnet_vampire_cb_apply_schema(s
, c
);
573 WERROR
libnet_vampire_cb_store_chunk(void *private_data
,
574 const struct libnet_BecomeDC_StoreChunk
*c
)
576 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
578 struct dsdb_schema
*schema
;
579 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
580 uint32_t nc_object_count
;
581 uint32_t object_count
;
582 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
583 uint32_t nc_linked_attributes_count
;
584 uint32_t linked_attributes_count
;
585 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
586 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
;
587 struct dsdb_extended_replicated_objects
*objs
;
588 uint32_t req_replica_flags
;
589 uint32_t dsdb_repl_flags
= 0;
590 struct repsFromTo1
*s_dsa
;
593 uint64_t seq_num
= 0;
594 bool is_exop
= false;
595 struct ldb_dn
*partition_dn
= NULL
;
596 struct ldb_dn
*nc_root
= NULL
;
598 s_dsa
= talloc_zero(s
, struct repsFromTo1
);
600 return WERR_NOT_ENOUGH_MEMORY
;
602 s_dsa
->other_info
= talloc(s_dsa
, struct repsFromTo1OtherInfo
);
603 if (s_dsa
->other_info
== NULL
) {
604 return WERR_NOT_ENOUGH_MEMORY
;
607 switch (c
->ctr_level
) {
609 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
610 nc_object_count
= c
->ctr1
->extended_ret
; /* maybe w2k send this unexpected? */
611 object_count
= c
->ctr1
->object_count
;
612 first_object
= c
->ctr1
->first_object
;
613 nc_linked_attributes_count
= 0;
614 linked_attributes_count
= 0;
615 linked_attributes
= NULL
;
616 s_dsa
->highwatermark
= c
->ctr1
->new_highwatermark
;
617 s_dsa
->source_dsa_obj_guid
= c
->ctr1
->source_dsa_guid
;
618 s_dsa
->source_dsa_invocation_id
= c
->ctr1
->source_dsa_invocation_id
;
619 uptodateness_vector
= NULL
; /* TODO: map it */
622 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
623 nc_object_count
= c
->ctr6
->nc_object_count
;
624 object_count
= c
->ctr6
->object_count
;
625 first_object
= c
->ctr6
->first_object
;
626 nc_linked_attributes_count
= c
->ctr6
->nc_linked_attributes_count
;
627 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
628 linked_attributes
= c
->ctr6
->linked_attributes
;
629 s_dsa
->highwatermark
= c
->ctr6
->new_highwatermark
;
630 s_dsa
->source_dsa_obj_guid
= c
->ctr6
->source_dsa_guid
;
631 s_dsa
->source_dsa_invocation_id
= c
->ctr6
->source_dsa_invocation_id
;
632 uptodateness_vector
= c
->ctr6
->uptodateness_vector
;
635 return WERR_INVALID_PARAMETER
;
638 switch (c
->req_level
) {
641 req_replica_flags
= 0;
644 if (c
->req5
->extended_op
!= DRSUAPI_EXOP_NONE
) {
647 req_replica_flags
= c
->req5
->replica_flags
;
650 if (c
->req8
->extended_op
!= DRSUAPI_EXOP_NONE
) {
653 req_replica_flags
= c
->req8
->replica_flags
;
656 if (c
->req10
->extended_op
!= DRSUAPI_EXOP_NONE
) {
659 req_replica_flags
= c
->req10
->replica_flags
;
661 if (c
->req10
->more_flags
& DRSUAPI_DRS_GET_TGT
) {
662 dsdb_repl_flags
|= DSDB_REPL_FLAG_TARGETS_UPTODATE
;
666 return WERR_INVALID_PARAMETER
;
670 * If the peer DC doesn't support GET_TGT (req v10), then the link
671 * targets are as up-to-date as they're ever gonna be. (Without this,
672 * cases where we'd normally retry with GET_TGT cause the join to fail)
674 if (c
->req_level
< 10) {
675 dsdb_repl_flags
|= DSDB_REPL_FLAG_TARGETS_UPTODATE
;
678 if (req_replica_flags
& DRSUAPI_DRS_CRITICAL_ONLY
|| is_exop
) {
680 * If we only replicate the critical objects, or this
681 * is an exop we should not remember what we already
682 * got, as it is incomplete.
684 ZERO_STRUCT(s_dsa
->highwatermark
);
685 uptodateness_vector
= NULL
;
686 dsdb_repl_flags
|= DSDB_REPL_FLAG_OBJECT_SUBSET
;
689 /* TODO: avoid hardcoded flags */
690 s_dsa
->replica_flags
= DRSUAPI_DRS_WRIT_REP
691 | DRSUAPI_DRS_INIT_SYNC
692 | DRSUAPI_DRS_PER_SYNC
;
693 memset(s_dsa
->schedule
, 0x11, sizeof(s_dsa
->schedule
));
695 tmp_dns_name
= GUID_string(s_dsa
->other_info
, &s_dsa
->source_dsa_obj_guid
);
696 if (tmp_dns_name
== NULL
) {
697 return WERR_NOT_ENOUGH_MEMORY
;
699 tmp_dns_name
= talloc_asprintf_append_buffer(tmp_dns_name
, "._msdcs.%s", c
->forest
->dns_name
);
700 if (tmp_dns_name
== NULL
) {
701 return WERR_NOT_ENOUGH_MEMORY
;
703 s_dsa
->other_info
->dns_name
= tmp_dns_name
;
705 /* we want to show a count per partition */
706 if (!s
->last_partition
|| strcmp(s
->last_partition
, c
->partition
->nc
.dn
) != 0) {
707 s
->total_objects
= 0;
709 talloc_free(s
->last_partition
);
710 s
->last_partition
= talloc_strdup(s
, c
->partition
->nc
.dn
);
712 s
->total_objects
+= object_count
;
713 s
->total_links
+= linked_attributes_count
;
715 partition_dn
= ldb_dn_new(s_dsa
, s
->ldb
, c
->partition
->nc
.dn
);
716 if (partition_dn
== NULL
) {
717 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
718 return WERR_INVALID_PARAMETER
;
723 if (nc_object_count
) {
724 DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
725 c
->partition
->nc
.dn
, s
->total_objects
, nc_object_count
,
726 s
->total_links
, nc_linked_attributes_count
));
728 DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
729 c
->partition
->nc
.dn
, s
->total_objects
, linked_attributes_count
));
731 ret
= dsdb_find_nc_root(s
->ldb
, s_dsa
,
732 partition_dn
, &nc_root
);
733 if (ret
!= LDB_SUCCESS
) {
734 DEBUG(0,(__location__
": Failed to find nc_root for %s\n",
735 ldb_dn_get_linearized(partition_dn
)));
736 return WERR_INTERNAL_ERROR
;
739 if (nc_object_count
) {
740 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
741 c
->partition
->nc
.dn
, s
->total_objects
, nc_object_count
,
742 s
->total_links
, nc_linked_attributes_count
));
744 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
745 c
->partition
->nc
.dn
, s
->total_objects
, s
->total_links
));
747 nc_root
= partition_dn
;
751 schema
= dsdb_get_schema(s
->ldb
, NULL
);
753 DEBUG(0,(__location__
": Schema is not loaded yet!\n"));
754 return WERR_INTERNAL_ERROR
;
757 if (req_replica_flags
& DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
) {
758 dsdb_repl_flags
|= DSDB_REPL_FLAG_PRIORITISE_INCOMING
;
761 if (req_replica_flags
& DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING
) {
762 dsdb_repl_flags
|= DSDB_REPL_FLAG_EXPECT_NO_SECRETS
;
765 status
= dsdb_replicated_objects_convert(s
->ldb
,
771 linked_attributes_count
,
778 if (!W_ERROR_IS_OK(status
)) {
779 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status
)));
783 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
784 for (i
=0; i
< objs
->num_objects
; i
++) {
785 struct ldb_ldif ldif
;
786 fprintf(stdout
, "#\n");
787 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
788 ldif
.msg
= objs
->objects
[i
].msg
;
789 ldb_ldif_write_file(s
->ldb
, stdout
, &ldif
);
790 NDR_PRINT_DEBUG(replPropertyMetaDataBlob
, objs
->objects
[i
].meta_data
);
793 status
= dsdb_replicated_objects_commit(s
->ldb
, NULL
, objs
, &seq_num
);
794 if (!W_ERROR_IS_OK(status
)) {
795 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status
)));
799 /* reset debug counters once we've finished replicating the partition */
800 if (!c
->partition
->more_data
) {
801 s
->total_objects
= 0;
808 for (i
=0; i
< linked_attributes_count
; i
++) {
809 const struct dsdb_attribute
*sa
;
811 if (!linked_attributes
[i
].identifier
) {
812 DEBUG(0, ("No linked attribute identifier\n"));
813 return WERR_INTERNAL_ERROR
;
816 if (!linked_attributes
[i
].value
.blob
) {
817 DEBUG(0, ("No linked attribute value\n"));
818 return WERR_INTERNAL_ERROR
;
821 sa
= dsdb_attribute_by_attributeID_id(s
->schema
,
822 linked_attributes
[i
].attid
);
824 DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes
[i
].attid
));
825 return WERR_INTERNAL_ERROR
;
828 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
829 DEBUG(0,("# %s\n", sa
->lDAPDisplayName
));
830 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute
, &linked_attributes
[i
]);
832 linked_attributes
[i
].value
.blob
->data
,
833 linked_attributes
[i
].value
.blob
->length
);