wafsamba: Do not remove BUILTINS as duplicates
[Samba.git] / source4 / libnet / libnet_vampire.c
blob6167493c359efa8f35481cc5aac4946b13ae541b
1 /*
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/>.
25 #include "includes.h"
26 #include "libnet/libnet.h"
27 #include "lib/events/events.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/dlinklist.h"
30 #include <ldb.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"
37 #include "ldb_wrap.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"
45 #undef DBGC_CLASS
46 #define DBGC_CLASS DBGC_DRS_REPL
48 /*
49 List of tasks vampire.py must perform:
50 - Domain Join
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;
64 const char *realm;
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;
80 struct {
81 uint32_t object_count;
82 struct drsuapi_DsReplicaObjectListItemEx *first_object;
83 struct drsuapi_DsReplicaObjectListItemEx *last_object;
84 } schema_part;
86 const char *targetdir;
88 struct loadparm_context *lp_ctx;
89 struct tevent_context *event_ctx;
90 unsigned total_objects;
91 unsigned total_links;
92 char *last_partition;
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);
102 if (!s) {
103 return NULL;
106 s->ldb = samdb;
107 s->lp_ctx = lp_ctx;
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);
114 return s;
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);
124 if (!s) {
125 return NULL;
128 s->lp_ctx = lp_ctx;
129 s->event_ctx = event_ctx;
130 s->netbios_name = netbios_name;
131 s->domain_name = domain_name;
132 s->realm = realm;
133 s->targetdir = targetdir;
134 return s;
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);
140 return state->ldb;
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;
155 NTSTATUS status;
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)) {
173 return 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;
194 return NT_STATUS_OK;
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",
205 s->netbios_name,
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));
220 return NT_STATUS_OK;
223 static WERROR libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
224 const struct libnet_BecomeDC_StoreChunk *c)
226 WERROR status;
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;
237 char *tmp_dns_name;
238 struct ldb_context *schema_ldb;
239 struct ldb_dn *partition_dn;
240 struct ldb_message *msg;
241 struct ldb_message_element *prefixMap_el;
242 uint32_t i;
243 int ret;
244 bool ok;
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);
251 if (s_dsa == NULL) {
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) {
260 case 1:
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 */
270 break;
271 case 6:
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;
281 break;
282 default:
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);
288 if (!ok) {
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);
293 if (!ok) {
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)));
303 return 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,
328 &s->prefixmap_blob);
329 if (!schema_ldb) {
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);
333 } else {
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,
344 "become dc",
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,
351 pfm_remote,
352 cycle_before_switching,
353 provision_schema,
354 s->self_made_schema,
355 object_count,
356 first_object);
357 if (!W_ERROR_IS_OK(status)) {
358 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
359 __location__, win_errstr(status)));
360 return 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,
390 s->schema,
391 partition_dn,
392 mapping_ctr,
393 object_count,
394 first_object,
395 linked_attributes_count,
396 linked_attributes,
397 s_dsa,
398 uptodateness_vector,
399 c->gensec_skey,
401 s, &schema_objs);
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)));
404 return 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)));
421 return status;
424 msg = ldb_msg_new(schema_objs);
425 if (msg == NULL) {
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;
450 talloc_free(s_dsa);
451 talloc_free(schema_objs);
453 s->schema = dsdb_get_schema(s->ldb, s);
454 if (!s->schema) {
455 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
456 return WERR_INTERNAL_ERROR;
459 return WERR_OK;
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);
466 WERROR werr;
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) {
477 case 1:
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;
484 break;
485 case 6:
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;
492 break;
493 default:
494 return WERR_INVALID_PARAMETER;
497 if (!s->schema_part.first_object) {
498 nc_total_received = object_count;
499 } else {
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));
506 } else {
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)) {
526 return 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
532 * other. */
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)) {
540 return werr;
542 } else {
543 werr = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
544 if (!W_ERROR_IS_OK(werr)) {
545 return 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);
552 } else {
553 s->schema_part.object_count += object_count;
554 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
555 first_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);
564 return WERR_OK;
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);
571 WERROR status;
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;
585 char *tmp_dns_name;
586 uint32_t i;
587 uint64_t seq_num;
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);
593 if (s_dsa == NULL) {
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) {
602 case 1:
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 */
614 break;
615 case 6:
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;
627 break;
628 default:
629 return WERR_INVALID_PARAMETER;
632 switch (c->req_level) {
633 case 0:
634 /* none */
635 req_replica_flags = 0;
636 break;
637 case 5:
638 if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
639 is_exop = true;
641 req_replica_flags = c->req5->replica_flags;
642 break;
643 case 8:
644 if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
645 is_exop = true;
647 req_replica_flags = c->req8->replica_flags;
648 break;
649 case 10:
650 if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
651 is_exop = true;
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;
658 break;
659 default:
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;
693 s->total_links = 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;
706 if (is_exop) {
707 int ret;
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));
712 } else {
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;
723 } else {
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));
728 } else {
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);
737 if (!schema) {
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,
751 schema,
752 nc_root,
753 mapping_ctr,
754 object_count,
755 first_object,
756 linked_attributes_count,
757 linked_attributes,
758 s_dsa,
759 uptodateness_vector,
760 c->gensec_skey,
761 dsdb_repl_flags,
762 s, &objs);
763 if (!W_ERROR_IS_OK(status)) {
764 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
765 return 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)));
781 return status;
784 /* reset debug counters once we've finished replicating the partition */
785 if (!c->partition->more_data) {
786 s->total_objects = 0;
787 s->total_links = 0;
790 talloc_free(s_dsa);
791 talloc_free(objs);
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);
808 if (!sa) {
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]);
816 dump_data(0,
817 linked_attributes[i].value.blob->data,
818 linked_attributes[i].value.blob->length);
822 return WERR_OK;