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"
30 #include "lib/ldb/include/ldb.h"
31 #include "lib/ldb/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/dom_sid.h"
45 List of tasks vampire.py must perform:
47 - but don't write the secrets.ldb
48 - results for this should be enough to handle the provision
49 - if vampire method is samsync
50 - Provision using these results
51 - do we still want to support this NT4 technology?
52 - Start samsync with libnet code
53 - provision in the callback
54 - Write out the secrets database, using the code from libnet_Join
57 struct libnet_vampire_cb_state {
58 const char *netbios_name;
59 const char *domain_name;
61 struct cli_credentials *machine_account;
63 /* Schema loaded from local LDIF files */
64 struct dsdb_schema *provision_schema;
66 /* 1st pass, with some OIDs/attribute names/class names not
67 * converted, because we may not know them yet */
68 struct dsdb_schema *self_made_schema;
70 /* 2nd pass, with full ID->OID->name table */
71 struct dsdb_schema *self_corrected_schema;
73 /* prefixMap in LDB format, from the remote DRS server */
74 DATA_BLOB prefixmap_blob;
75 const struct dsdb_schema *schema;
77 struct ldb_context *ldb;
80 uint32_t object_count;
81 struct drsuapi_DsReplicaObjectListItemEx *first_object;
82 struct drsuapi_DsReplicaObjectListItemEx *last_object;
85 const char *targetdir;
87 struct loadparm_context *lp_ctx;
88 struct tevent_context *event_ctx;
89 unsigned total_objects;
93 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
94 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
95 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
96 const char *netbios_name, const char *domain_name, const char *realm,
97 const char *targetdir)
99 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
105 s->event_ctx = event_ctx;
106 s->netbios_name = netbios_name;
107 s->domain_name = domain_name;
109 s->targetdir = targetdir;
113 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
115 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
119 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
121 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
122 return state->lp_ctx;
125 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
126 const struct libnet_BecomeDC_PrepareDB *p)
128 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
129 struct provision_settings settings;
130 struct provision_result result;
133 ZERO_STRUCT(settings);
134 settings.site_name = p->dest_dsa->site_name;
135 settings.root_dn_str = p->forest->root_dn_str;
136 settings.domain_dn_str = p->domain->dn_str;
137 settings.config_dn_str = p->forest->config_dn_str;
138 settings.schema_dn_str = p->forest->schema_dn_str;
139 settings.netbios_name = p->dest_dsa->netbios_name;
140 settings.realm = s->realm;
141 settings.domain = s->domain_name;
142 settings.server_dn_str = p->dest_dsa->server_dn_str;
143 settings.machine_password = generate_random_password(s, 16, 255);
144 settings.targetdir = s->targetdir;
146 status = provision_bare(s, s->lp_ctx, &settings, &result);
148 if (!NT_STATUS_IS_OK(status)) {
152 s->ldb = talloc_steal(s, result.samdb);
153 s->lp_ctx = talloc_steal(s, result.lp_ctx);
154 s->provision_schema = dsdb_get_schema(s->ldb, s);
156 /* wrap the entire vapire operation in a transaction. This
157 isn't just cosmetic - we use this to ensure that linked
158 attribute back links are added at the end by relying on a
159 transaction commit hook in the linked attributes module. We
160 need to do this as the order of objects coming from the
161 server is not sufficiently deterministic to know that the
162 record that a backlink needs to be created in has itself
163 been created before the object containing the forward link
164 has come over the wire */
165 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
166 return NT_STATUS_FOOBAR;
174 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
175 const struct libnet_BecomeDC_CheckOptions *o)
177 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
179 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
181 o->domain->netbios_name, o->domain->dns_name));
183 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
184 o->source_dsa->dns_name, o->source_dsa->site_name));
186 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
187 "\tschema object_version[%u]\n"
188 "\tdomain behavior_version[%u]\n"
189 "\tdomain w2k3_update_revision[%u]\n",
190 o->forest->crossref_behavior_version,
191 o->forest->schema_object_version,
192 o->domain->behavior_version,
193 o->domain->w2k3_update_revision));
198 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
199 const struct libnet_BecomeDC_StoreChunk *c)
202 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
203 uint32_t object_count;
204 struct drsuapi_DsReplicaObjectListItemEx *first_object;
205 const struct drsuapi_DsReplicaObjectListItemEx *cur;
206 uint32_t linked_attributes_count;
207 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
208 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
209 struct dsdb_extended_replicated_objects *schema_objs;
210 struct repsFromTo1 *s_dsa;
212 struct ldb_context *schema_ldb;
213 struct ldb_message *msg;
214 struct ldb_message_element *prefixMap_el;
220 DEBUG(0,("Analyze and apply schema objects\n"));
222 s_dsa = talloc_zero(s, struct repsFromTo1);
223 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
224 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
225 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
227 switch (c->ctr_level) {
229 mapping_ctr = &c->ctr1->mapping_ctr;
230 object_count = s->schema_part.object_count;
231 first_object = s->schema_part.first_object;
232 linked_attributes_count = 0;
233 linked_attributes = NULL;
234 s_dsa->highwatermark = c->ctr1->new_highwatermark;
235 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
236 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
237 uptodateness_vector = NULL; /* TODO: map it */
240 mapping_ctr = &c->ctr6->mapping_ctr;
241 object_count = s->schema_part.object_count;
242 first_object = s->schema_part.first_object;
243 linked_attributes_count = c->ctr6->linked_attributes_count;
244 linked_attributes = c->ctr6->linked_attributes;
245 s_dsa->highwatermark = c->ctr6->new_highwatermark;
246 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
247 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
248 uptodateness_vector = c->ctr6->uptodateness_vector;
251 return NT_STATUS_INVALID_PARAMETER;
254 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
255 | DRSUAPI_DRS_INIT_SYNC
256 | DRSUAPI_DRS_PER_SYNC;
257 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
259 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
260 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
261 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
262 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
263 s_dsa->other_info->dns_name = tmp_dns_name;
265 schema_ldb = provision_get_schema(s, s->lp_ctx, &s->prefixmap_blob);
267 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. Will continue with local prefixMap\n"));
268 s->provision_schema = dsdb_get_schema(s->ldb, s);
270 s->provision_schema = dsdb_get_schema(schema_ldb, s);
271 ret = dsdb_reference_schema(s->ldb, s->provision_schema, false);
272 if (ret != LDB_SUCCESS) {
273 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
274 return NT_STATUS_UNSUCCESSFUL;
276 talloc_free(schema_ldb);
279 s->provision_schema->relax_OID_conversions = true;
281 /* Now convert the schema elements, using the schema we loaded locally */
282 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
283 struct dsdb_extended_replicated_object object;
284 TALLOC_CTX *tmp_ctx = talloc_new(s);
285 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
287 /* Convert the objects into LDB messages using the
288 * provision schema, and either the provision or DRS
289 * prefix map - it should not matter, as these are
290 * just schema objects, so the critical parts. At
291 * most we would mix up the mayContain etc for new
293 status = dsdb_convert_object_ex(s->ldb, s->provision_schema,
296 if (!W_ERROR_IS_OK(status)) {
297 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
299 /* Convert the schema from ldb_message format
300 * (OIDs as OID strings) into schema, using
301 * the remote prefixMap */
302 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_made_schema, object.msg);
303 if (!W_ERROR_IS_OK(status)) {
304 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
305 ldb_dn_get_linearized(object.msg->dn),
306 win_errstr(status)));
309 talloc_free(tmp_ctx);
312 /* attach the schema we just brought over DRS to the ldb, so we can use it in dsdb_convert_object_ex below */
313 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
314 if (ret != LDB_SUCCESS) {
315 DEBUG(0,("Failed to attach 1st pass schema from DRS.\n"));
316 return NT_STATUS_FOOBAR;
319 /* Now convert the schema elements again, using the schema we loaded over DRS */
320 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
321 struct dsdb_extended_replicated_object object;
322 TALLOC_CTX *tmp_ctx = talloc_new(s);
323 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
325 /* Convert the objects into LDB messages using the
326 * self_made_schema, and the DRS prefix map. We now
327 * know the full schema int->OID->name mapping, so we
328 * can get it right this time */
329 status = dsdb_convert_object_ex(s->ldb, s->self_made_schema,
332 if (!W_ERROR_IS_OK(status)) {
333 DEBUG(0,("ERROR: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
335 /* Convert the schema from ldb_message format
336 * (OIDs as OID strings) into schema, using
337 * the remote prefixMap, now that we know
338 * names for all the schema elements (from the
339 * first conversion) */
340 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_corrected_schema, object.msg);
341 if (!W_ERROR_IS_OK(status)) {
342 DEBUG(0,("ERROR: failed to convert object %s into a schema element: %s\n",
343 ldb_dn_get_linearized(object.msg->dn),
344 win_errstr(status)));
347 talloc_free(tmp_ctx);
350 /* We don't want to use the s->self_made_schema any more */
351 s->self_made_schema = NULL;
353 /* attach the schema we just brought over DRS to the ldb */
354 ret = dsdb_set_schema(s->ldb, s->self_corrected_schema);
355 if (ret != LDB_SUCCESS) {
356 DEBUG(0,("Failed to attach 2nd pass (corrected) schema from DRS.\n"));
357 return NT_STATUS_FOOBAR;
360 /* we don't want to access the self made schema anymore */
361 s->schema = s->self_corrected_schema;
362 s->self_corrected_schema = NULL;
364 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
365 status = dsdb_extended_replicated_objects_convert(s->ldb,
370 linked_attributes_count,
376 if (!W_ERROR_IS_OK(status)) {
377 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
378 return werror_to_ntstatus(status);
381 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
382 for (i=0; i < schema_objs->num_objects; i++) {
383 struct ldb_ldif ldif;
384 fprintf(stdout, "#\n");
385 ldif.changetype = LDB_CHANGETYPE_NONE;
386 ldif.msg = schema_objs->objects[i].msg;
387 ldb_ldif_write_file(s->ldb, stdout, &ldif);
388 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
392 status = dsdb_extended_replicated_objects_commit(s->ldb, schema_objs, &seq_num);
393 if (!W_ERROR_IS_OK(status)) {
394 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
395 return werror_to_ntstatus(status);
398 msg = ldb_msg_new(schema_objs);
399 NT_STATUS_HAVE_NO_MEMORY(msg);
400 msg->dn = schema_objs->partition_dn;
402 /* We must ensure a prefixMap has been written. Unlike other
403 * attributes (including schemaInfo), it is not replicated in
404 * the normal replication stream. We can use the one from
405 * s->prefixmap_blob because we operate with one, unchanging
406 * prefixMap for this entire operation. */
407 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
408 if (ret != LDB_SUCCESS) {
409 return NT_STATUS_FOOBAR;
411 /* We want to know if a prefixMap was written already, as it
412 * would mean that the above comment was not true, and we have
413 * somehow updated the prefixMap during this transaction */
414 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
416 ret = ldb_modify(s->ldb, msg);
417 if (ret != LDB_SUCCESS) {
418 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
419 return NT_STATUS_FOOBAR;
423 talloc_free(schema_objs);
425 /* We must set these up to ensure the replMetaData is written
426 * correctly, before our NTDS Settings entry is replicated */
427 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
429 DEBUG(0,("Failed to set cached ntds invocationId\n"));
430 return NT_STATUS_FOOBAR;
432 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
434 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
435 return NT_STATUS_FOOBAR;
438 s->schema = dsdb_get_schema(s->ldb, s);
440 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
441 return NT_STATUS_FOOBAR;
447 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
448 const struct libnet_BecomeDC_StoreChunk *c)
450 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
452 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
453 uint32_t nc_object_count;
454 uint32_t object_count;
455 struct drsuapi_DsReplicaObjectListItemEx *first_object;
456 struct drsuapi_DsReplicaObjectListItemEx *cur;
457 uint32_t nc_linked_attributes_count;
458 uint32_t linked_attributes_count;
459 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
461 switch (c->ctr_level) {
463 mapping_ctr = &c->ctr1->mapping_ctr;
464 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
465 object_count = c->ctr1->object_count;
466 first_object = c->ctr1->first_object;
467 nc_linked_attributes_count = 0;
468 linked_attributes_count = 0;
469 linked_attributes = NULL;
472 mapping_ctr = &c->ctr6->mapping_ctr;
473 nc_object_count = c->ctr6->nc_object_count;
474 object_count = c->ctr6->object_count;
475 first_object = c->ctr6->first_object;
476 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
477 linked_attributes_count = c->ctr6->linked_attributes_count;
478 linked_attributes = c->ctr6->linked_attributes;
481 return NT_STATUS_INVALID_PARAMETER;
484 if (nc_object_count) {
485 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
486 c->partition->nc.dn, object_count, nc_object_count,
487 linked_attributes_count, nc_linked_attributes_count));
489 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
490 c->partition->nc.dn, object_count, linked_attributes_count));
493 if (!s->self_made_schema) {
495 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
496 /* Put the DRS prefixmap aside for the schema we are
497 * about to load in the provision, and into the one we
498 * are making with the help of DRS */
500 mapping_ctr_without_schema_info = *mapping_ctr;
502 /* This strips off the 0xFF schema info from the end,
503 * because we don't want it in the blob */
504 if (mapping_ctr_without_schema_info.num_mappings > 0) {
505 mapping_ctr_without_schema_info.num_mappings--;
507 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
508 if (!W_ERROR_IS_OK(werr)) {
509 return werror_to_ntstatus(werr);
512 /* Set up two manually-constructed schema - the local
513 * schema from the provision will be used to build
514 * one, which will then in turn be used to build the
516 s->self_made_schema = dsdb_new_schema(s);
517 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
518 s->self_corrected_schema = dsdb_new_schema(s);
519 NT_STATUS_HAVE_NO_MEMORY(s->self_corrected_schema);
521 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
522 if (!W_ERROR_IS_OK(status)) {
523 return werror_to_ntstatus(status);
526 status = dsdb_load_prefixmap_from_drsuapi(s->self_corrected_schema, mapping_ctr);
527 if (!W_ERROR_IS_OK(status)) {
528 return werror_to_ntstatus(status);
531 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
532 if (!W_ERROR_IS_OK(status)) {
533 return werror_to_ntstatus(status);
537 if (!s->schema_part.first_object) {
538 s->schema_part.object_count = object_count;
539 s->schema_part.first_object = talloc_steal(s, first_object);
541 s->schema_part.object_count += object_count;
542 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
545 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
546 s->schema_part.last_object = cur;
548 if (!c->partition->more_data) {
549 return libnet_vampire_cb_apply_schema(s, c);
555 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
556 const struct libnet_BecomeDC_StoreChunk *c)
558 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
560 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
561 uint32_t nc_object_count;
562 uint32_t object_count;
563 struct drsuapi_DsReplicaObjectListItemEx *first_object;
564 uint32_t nc_linked_attributes_count;
565 uint32_t linked_attributes_count;
566 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
567 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
568 struct dsdb_extended_replicated_objects *objs;
569 struct repsFromTo1 *s_dsa;
574 s_dsa = talloc_zero(s, struct repsFromTo1);
575 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
576 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
577 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
579 switch (c->ctr_level) {
581 mapping_ctr = &c->ctr1->mapping_ctr;
582 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
583 object_count = c->ctr1->object_count;
584 first_object = c->ctr1->first_object;
585 nc_linked_attributes_count = 0;
586 linked_attributes_count = 0;
587 linked_attributes = NULL;
588 s_dsa->highwatermark = c->ctr1->new_highwatermark;
589 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
590 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
591 uptodateness_vector = NULL; /* TODO: map it */
594 mapping_ctr = &c->ctr6->mapping_ctr;
595 nc_object_count = c->ctr6->nc_object_count;
596 object_count = c->ctr6->object_count;
597 first_object = c->ctr6->first_object;
598 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
599 linked_attributes_count = c->ctr6->linked_attributes_count;
600 linked_attributes = c->ctr6->linked_attributes;
601 s_dsa->highwatermark = c->ctr6->new_highwatermark;
602 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
603 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
604 uptodateness_vector = c->ctr6->uptodateness_vector;
607 return NT_STATUS_INVALID_PARAMETER;
610 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
611 | DRSUAPI_DRS_INIT_SYNC
612 | DRSUAPI_DRS_PER_SYNC;
613 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
615 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
616 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
617 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
618 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
619 s_dsa->other_info->dns_name = tmp_dns_name;
621 /* we want to show a count per partition */
622 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
623 s->total_objects = 0;
624 talloc_free(s->last_partition);
625 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
627 s->total_objects += object_count;
629 if (nc_object_count) {
630 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
631 c->partition->nc.dn, s->total_objects, nc_object_count,
632 linked_attributes_count, nc_linked_attributes_count));
634 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
635 c->partition->nc.dn, s->total_objects, linked_attributes_count));
639 status = dsdb_extended_replicated_objects_convert(s->ldb,
644 linked_attributes_count,
650 if (!W_ERROR_IS_OK(status)) {
651 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
652 return werror_to_ntstatus(status);
655 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
656 for (i=0; i < objs->num_objects; i++) {
657 struct ldb_ldif ldif;
658 fprintf(stdout, "#\n");
659 ldif.changetype = LDB_CHANGETYPE_NONE;
660 ldif.msg = objs->objects[i].msg;
661 ldb_ldif_write_file(s->ldb, stdout, &ldif);
662 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
665 status = dsdb_extended_replicated_objects_commit(s->ldb,
667 if (!W_ERROR_IS_OK(status)) {
668 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
669 return werror_to_ntstatus(status);
675 for (i=0; i < linked_attributes_count; i++) {
676 const struct dsdb_attribute *sa;
678 if (!linked_attributes[i].identifier) {
679 return NT_STATUS_FOOBAR;
682 if (!linked_attributes[i].value.blob) {
683 return NT_STATUS_FOOBAR;
686 sa = dsdb_attribute_by_attributeID_id(s->schema,
687 linked_attributes[i].attid);
689 return NT_STATUS_FOOBAR;
692 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
693 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
694 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
696 linked_attributes[i].value.blob->data,
697 linked_attributes[i].value.blob->length);
704 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
705 struct libnet_Vampire *r)
707 struct libnet_JoinDomain *join;
708 struct provision_store_self_join_settings *set_secrets;
709 struct libnet_BecomeDC b;
710 struct libnet_vampire_cb_state *s;
711 struct ldb_message *msg;
712 const char *error_string;
717 const char *account_name;
718 const char *netbios_name;
720 r->out.error_string = NULL;
722 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
724 return NT_STATUS_NO_MEMORY;
727 if (r->in.netbios_name != NULL) {
728 netbios_name = r->in.netbios_name;
730 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
733 r->out.error_string = NULL;
734 return NT_STATUS_NO_MEMORY;
738 account_name = talloc_asprintf(join, "%s$", netbios_name);
741 r->out.error_string = NULL;
742 return NT_STATUS_NO_MEMORY;
745 /* Re-use the domain we are joining as the domain for the user
746 * to be authenticated with, unless they specified
748 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
750 join->in.domain_name = r->in.domain_name;
751 join->in.account_name = account_name;
752 join->in.netbios_name = netbios_name;
753 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
754 join->in.acct_type = ACB_WSTRUST;
755 join->in.recreate_account = false;
756 status = libnet_JoinDomain(ctx, join, join);
757 if (!NT_STATUS_IS_OK(status)) {
758 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
763 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
764 netbios_name, join->out.domain_name, join->out.realm,
767 return NT_STATUS_NO_MEMORY;
769 talloc_steal(s, join);
774 * We now know the domain and realm for sure - if they didn't
775 * put one on the command line, use this for the rest of the
777 cli_credentials_set_realm(ctx->cred, join->out.realm, CRED_GUESS_ENV);
778 cli_credentials_set_domain(ctx->cred, join->out.domain_name, CRED_GUESS_ENV);
780 /* Now set these values into the smb.conf - we probably had
781 * empty or useless defaults here from whatever smb.conf we
783 lp_set_cmdline(s->lp_ctx, "realm", join->out.realm);
784 lp_set_cmdline(s->lp_ctx, "workgroup", join->out.domain_name);
786 b.in.domain_dns_name = join->out.realm;
787 b.in.domain_netbios_name = join->out.domain_name;
788 b.in.domain_sid = join->out.domain_sid;
789 b.in.source_dsa_address = join->out.samr_binding->host;
790 b.in.dest_dsa_netbios_name = netbios_name;
792 b.in.callbacks.private_data = s;
793 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
794 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
795 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
796 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
797 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
799 b.in.rodc_join = lp_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
801 status = libnet_BecomeDC(ctx, s, &b);
802 if (!NT_STATUS_IS_OK(status)) {
803 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
808 msg = ldb_msg_new(s);
810 printf("ldb_msg_new() failed\n");
812 return NT_STATUS_NO_MEMORY;
814 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
816 printf("ldb_msg_new(@ROOTDSE) failed\n");
818 return NT_STATUS_NO_MEMORY;
821 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
822 if (ldb_ret != LDB_SUCCESS) {
823 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
825 return NT_STATUS_NO_MEMORY;
828 for (i=0; i < msg->num_elements; i++) {
829 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
832 printf("mark ROOTDSE with isSynchronized=TRUE\n");
833 ldb_ret = ldb_modify(s->ldb, msg);
834 if (ldb_ret != LDB_SUCCESS) {
835 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
837 return NT_STATUS_INTERNAL_DB_ERROR;
840 /* prepare the transaction - this prepares to commit all the changes in
841 the ldb from the whole vampire. Note that this
842 triggers the writing of the linked attribute backlinks.
844 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
845 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
846 return NT_STATUS_INTERNAL_DB_ERROR;
849 set_secrets = talloc(s, struct provision_store_self_join_settings);
851 r->out.error_string = NULL;
853 return NT_STATUS_NO_MEMORY;
856 ZERO_STRUCTP(set_secrets);
857 set_secrets->domain_name = join->out.domain_name;
858 set_secrets->realm = join->out.realm;
859 set_secrets->netbios_name = netbios_name;
860 set_secrets->secure_channel_type = SEC_CHAN_BDC;
861 set_secrets->machine_password = join->out.join_password;
862 set_secrets->key_version_number = join->out.kvno;
863 set_secrets->domain_sid = join->out.domain_sid;
865 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
866 if (!NT_STATUS_IS_OK(status)) {
867 r->out.error_string = talloc_steal(mem_ctx, error_string);
872 r->out.domain_name = talloc_steal(mem_ctx, join->out.domain_name);
873 r->out.domain_sid = dom_sid_dup(mem_ctx, join->out.domain_sid);
875 /* commit the transaction now we know the secrets were written
878 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
879 printf("Failed to commit vampire transaction\n");
880 return NT_STATUS_INTERNAL_DB_ERROR;