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
, 120, 120);
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_unlink(s
, 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 if (first_object
!= NULL
) {
558 for (cur
= first_object
; cur
->next_object
; cur
= cur
->next_object
) {}
563 s
->schema_part
.last_object
= cur
;
565 if (!c
->partition
->more_data
) {
566 return libnet_vampire_cb_apply_schema(s
, c
);
572 WERROR
libnet_vampire_cb_store_chunk(void *private_data
,
573 const struct libnet_BecomeDC_StoreChunk
*c
)
575 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
577 struct dsdb_schema
*schema
;
578 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
579 uint32_t nc_object_count
;
580 uint32_t object_count
;
581 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
582 uint32_t nc_linked_attributes_count
;
583 uint32_t linked_attributes_count
;
584 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
585 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
;
586 struct dsdb_extended_replicated_objects
*objs
;
587 uint32_t req_replica_flags
;
588 uint32_t dsdb_repl_flags
= 0;
589 struct repsFromTo1
*s_dsa
;
592 uint64_t seq_num
= 0;
593 bool is_exop
= false;
594 struct ldb_dn
*partition_dn
= NULL
;
595 struct ldb_dn
*nc_root
= NULL
;
597 s_dsa
= talloc_zero(s
, struct repsFromTo1
);
599 return WERR_NOT_ENOUGH_MEMORY
;
601 s_dsa
->other_info
= talloc(s_dsa
, struct repsFromTo1OtherInfo
);
602 if (s_dsa
->other_info
== NULL
) {
603 return WERR_NOT_ENOUGH_MEMORY
;
606 switch (c
->ctr_level
) {
608 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
609 nc_object_count
= c
->ctr1
->extended_ret
; /* maybe w2k send this unexpected? */
610 object_count
= c
->ctr1
->object_count
;
611 first_object
= c
->ctr1
->first_object
;
612 nc_linked_attributes_count
= 0;
613 linked_attributes_count
= 0;
614 linked_attributes
= NULL
;
615 s_dsa
->highwatermark
= c
->ctr1
->new_highwatermark
;
616 s_dsa
->source_dsa_obj_guid
= c
->ctr1
->source_dsa_guid
;
617 s_dsa
->source_dsa_invocation_id
= c
->ctr1
->source_dsa_invocation_id
;
618 uptodateness_vector
= NULL
; /* TODO: map it */
621 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
622 nc_object_count
= c
->ctr6
->nc_object_count
;
623 object_count
= c
->ctr6
->object_count
;
624 first_object
= c
->ctr6
->first_object
;
625 nc_linked_attributes_count
= c
->ctr6
->nc_linked_attributes_count
;
626 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
627 linked_attributes
= c
->ctr6
->linked_attributes
;
628 s_dsa
->highwatermark
= c
->ctr6
->new_highwatermark
;
629 s_dsa
->source_dsa_obj_guid
= c
->ctr6
->source_dsa_guid
;
630 s_dsa
->source_dsa_invocation_id
= c
->ctr6
->source_dsa_invocation_id
;
631 uptodateness_vector
= c
->ctr6
->uptodateness_vector
;
634 return WERR_INVALID_PARAMETER
;
637 switch (c
->req_level
) {
640 req_replica_flags
= 0;
643 if (c
->req5
->extended_op
!= DRSUAPI_EXOP_NONE
) {
646 req_replica_flags
= c
->req5
->replica_flags
;
649 if (c
->req8
->extended_op
!= DRSUAPI_EXOP_NONE
) {
652 req_replica_flags
= c
->req8
->replica_flags
;
655 if (c
->req10
->extended_op
!= DRSUAPI_EXOP_NONE
) {
658 req_replica_flags
= c
->req10
->replica_flags
;
660 if (c
->req10
->more_flags
& DRSUAPI_DRS_GET_TGT
) {
661 dsdb_repl_flags
|= DSDB_REPL_FLAG_TARGETS_UPTODATE
;
665 return WERR_INVALID_PARAMETER
;
669 * If the peer DC doesn't support GET_TGT (req v10), then the link
670 * targets are as up-to-date as they're ever gonna be. (Without this,
671 * cases where we'd normally retry with GET_TGT cause the join to fail)
673 if (c
->req_level
< 10) {
674 dsdb_repl_flags
|= DSDB_REPL_FLAG_TARGETS_UPTODATE
;
677 if (req_replica_flags
& DRSUAPI_DRS_CRITICAL_ONLY
|| is_exop
) {
679 * If we only replicate the critical objects, or this
680 * is an exop we should not remember what we already
681 * got, as it is incomplete.
683 ZERO_STRUCT(s_dsa
->highwatermark
);
684 uptodateness_vector
= NULL
;
685 dsdb_repl_flags
|= DSDB_REPL_FLAG_OBJECT_SUBSET
;
688 /* TODO: avoid hardcoded flags */
689 s_dsa
->replica_flags
= DRSUAPI_DRS_WRIT_REP
690 | DRSUAPI_DRS_INIT_SYNC
691 | DRSUAPI_DRS_PER_SYNC
;
692 memset(s_dsa
->schedule
, 0x11, sizeof(s_dsa
->schedule
));
694 tmp_dns_name
= GUID_string(s_dsa
->other_info
, &s_dsa
->source_dsa_obj_guid
);
695 if (tmp_dns_name
== NULL
) {
696 return WERR_NOT_ENOUGH_MEMORY
;
698 tmp_dns_name
= talloc_asprintf_append_buffer(tmp_dns_name
, "._msdcs.%s", c
->forest
->dns_name
);
699 if (tmp_dns_name
== NULL
) {
700 return WERR_NOT_ENOUGH_MEMORY
;
702 s_dsa
->other_info
->dns_name
= tmp_dns_name
;
704 /* we want to show a count per partition */
705 if (!s
->last_partition
|| strcmp(s
->last_partition
, c
->partition
->nc
.dn
) != 0) {
706 s
->total_objects
= 0;
708 talloc_free(s
->last_partition
);
709 s
->last_partition
= talloc_strdup(s
, c
->partition
->nc
.dn
);
711 s
->total_objects
+= object_count
;
712 s
->total_links
+= linked_attributes_count
;
714 partition_dn
= ldb_dn_new(s_dsa
, s
->ldb
, c
->partition
->nc
.dn
);
715 if (partition_dn
== NULL
) {
716 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
717 return WERR_INVALID_PARAMETER
;
722 if (nc_object_count
) {
723 DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
724 c
->partition
->nc
.dn
, s
->total_objects
, nc_object_count
,
725 s
->total_links
, nc_linked_attributes_count
));
727 DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
728 c
->partition
->nc
.dn
, s
->total_objects
, linked_attributes_count
));
730 ret
= dsdb_find_nc_root(s
->ldb
, s_dsa
,
731 partition_dn
, &nc_root
);
732 if (ret
!= LDB_SUCCESS
) {
733 DEBUG(0,(__location__
": Failed to find nc_root for %s\n",
734 ldb_dn_get_linearized(partition_dn
)));
735 return WERR_INTERNAL_ERROR
;
738 if (nc_object_count
) {
739 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
740 c
->partition
->nc
.dn
, s
->total_objects
, nc_object_count
,
741 s
->total_links
, nc_linked_attributes_count
));
743 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
744 c
->partition
->nc
.dn
, s
->total_objects
, s
->total_links
));
746 nc_root
= partition_dn
;
750 schema
= dsdb_get_schema(s
->ldb
, NULL
);
752 DEBUG(0,(__location__
": Schema is not loaded yet!\n"));
753 return WERR_INTERNAL_ERROR
;
756 if (req_replica_flags
& DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
) {
757 dsdb_repl_flags
|= DSDB_REPL_FLAG_PRIORITISE_INCOMING
;
760 if (req_replica_flags
& DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING
) {
761 dsdb_repl_flags
|= DSDB_REPL_FLAG_EXPECT_NO_SECRETS
;
764 status
= dsdb_replicated_objects_convert(s
->ldb
,
770 linked_attributes_count
,
777 if (!W_ERROR_IS_OK(status
)) {
778 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status
)));
782 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
783 for (i
=0; i
< objs
->num_objects
; i
++) {
784 struct ldb_ldif ldif
;
785 fprintf(stdout
, "#\n");
786 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
787 ldif
.msg
= objs
->objects
[i
].msg
;
788 ldb_ldif_write_file(s
->ldb
, stdout
, &ldif
);
789 NDR_PRINT_DEBUG(replPropertyMetaDataBlob
, objs
->objects
[i
].meta_data
);
792 status
= dsdb_replicated_objects_commit(s
->ldb
, NULL
, objs
, &seq_num
);
793 if (!W_ERROR_IS_OK(status
)) {
794 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status
)));
798 /* reset debug counters once we've finished replicating the partition */
799 if (!c
->partition
->more_data
) {
800 s
->total_objects
= 0;
807 for (i
=0; i
< linked_attributes_count
; i
++) {
808 const struct dsdb_attribute
*sa
;
810 if (!linked_attributes
[i
].identifier
) {
811 DEBUG(0, ("No linked attribute identifier\n"));
812 return WERR_INTERNAL_ERROR
;
815 if (!linked_attributes
[i
].value
.blob
) {
816 DEBUG(0, ("No linked attribute value\n"));
817 return WERR_INTERNAL_ERROR
;
820 sa
= dsdb_attribute_by_attributeID_id(s
->schema
,
821 linked_attributes
[i
].attid
);
823 DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes
[i
].attid
));
824 return WERR_INTERNAL_ERROR
;
827 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
828 DEBUG(0,("# %s\n", sa
->lDAPDisplayName
));
829 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute
, &linked_attributes
[i
]);
831 linked_attributes
[i
].value
.blob
->data
,
832 linked_attributes
[i
].value
.blob
->length
);