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"
43 #include "dsdb/common/util.h"
46 List of tasks vampire.py must perform:
48 - but don't write the secrets.ldb
49 - results for this should be enough to handle the provision
50 - if vampire method is samsync
51 - Provision using these results
52 - do we still want to support this NT4 technology?
53 - Start samsync with libnet code
54 - provision in the callback
55 - Write out the secrets database, using the code from libnet_Join
58 struct libnet_vampire_cb_state {
59 const char *netbios_name;
60 const char *domain_name;
62 struct cli_credentials *machine_account;
64 /* Schema loaded from local LDIF files */
65 struct dsdb_schema *provision_schema;
67 /* 1st pass, with some OIDs/attribute names/class names not
68 * converted, because we may not know them yet */
69 struct dsdb_schema *self_made_schema;
71 /* 2nd pass, with full ID->OID->name table */
72 struct dsdb_schema *self_corrected_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;
92 const char *server_dn_str;
95 /* initialise a state structure ready for replication of chunks */
96 void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
97 struct ldb_context *samdb,
98 struct loadparm_context *lp_ctx)
100 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
107 s->provision_schema = dsdb_get_schema(s->ldb, s);
108 s->schema = s->provision_schema;
113 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
114 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
115 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
116 const char *netbios_name, const char *domain_name, const char *realm,
117 const char *targetdir)
119 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
125 s->event_ctx = event_ctx;
126 s->netbios_name = netbios_name;
127 s->domain_name = domain_name;
129 s->targetdir = targetdir;
133 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
135 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
139 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
141 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
142 return state->lp_ctx;
145 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
146 const struct libnet_BecomeDC_PrepareDB *p)
148 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
149 struct provision_settings settings;
150 struct provision_result result;
153 ZERO_STRUCT(settings);
154 settings.site_name = p->dest_dsa->site_name;
155 settings.root_dn_str = p->forest->root_dn_str;
156 settings.domain_dn_str = p->domain->dn_str;
157 settings.config_dn_str = p->forest->config_dn_str;
158 settings.schema_dn_str = p->forest->schema_dn_str;
159 settings.netbios_name = p->dest_dsa->netbios_name;
160 settings.realm = s->realm;
161 settings.domain = s->domain_name;
162 settings.server_dn_str = p->dest_dsa->server_dn_str;
163 settings.machine_password = generate_random_password(s, 16, 255);
164 settings.targetdir = s->targetdir;
166 status = provision_bare(s, s->lp_ctx, &settings, &result);
168 if (!NT_STATUS_IS_OK(status)) {
172 s->ldb = talloc_steal(s, result.samdb);
173 s->lp_ctx = talloc_steal(s, result.lp_ctx);
174 s->provision_schema = dsdb_get_schema(s->ldb, s);
175 s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
177 /* wrap the entire vapire operation in a transaction. This
178 isn't just cosmetic - we use this to ensure that linked
179 attribute back links are added at the end by relying on a
180 transaction commit hook in the linked attributes module. We
181 need to do this as the order of objects coming from the
182 server is not sufficiently deterministic to know that the
183 record that a backlink needs to be created in has itself
184 been created before the object containing the forward link
185 has come over the wire */
186 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
187 return NT_STATUS_FOOBAR;
195 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
196 const struct libnet_BecomeDC_CheckOptions *o)
198 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
200 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
202 o->domain->netbios_name, o->domain->dns_name));
204 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
205 o->source_dsa->dns_name, o->source_dsa->site_name));
207 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
208 "\tschema object_version[%u]\n"
209 "\tdomain behavior_version[%u]\n"
210 "\tdomain w2k3_update_revision[%u]\n",
211 o->forest->crossref_behavior_version,
212 o->forest->schema_object_version,
213 o->domain->behavior_version,
214 o->domain->w2k3_update_revision));
219 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
220 const struct libnet_BecomeDC_StoreChunk *c)
223 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
224 uint32_t object_count;
225 struct drsuapi_DsReplicaObjectListItemEx *first_object;
226 const struct drsuapi_DsReplicaObjectListItemEx *cur;
227 uint32_t linked_attributes_count;
228 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
229 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
230 struct dsdb_extended_replicated_objects *schema_objs;
231 struct repsFromTo1 *s_dsa;
233 struct ldb_context *schema_ldb;
234 struct ldb_message *msg;
235 struct ldb_message_element *prefixMap_el;
241 DEBUG(0,("Analyze and apply schema objects\n"));
243 s_dsa = talloc_zero(s, struct repsFromTo1);
244 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
245 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
246 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
248 switch (c->ctr_level) {
250 mapping_ctr = &c->ctr1->mapping_ctr;
251 object_count = s->schema_part.object_count;
252 first_object = s->schema_part.first_object;
253 linked_attributes_count = 0;
254 linked_attributes = NULL;
255 s_dsa->highwatermark = c->ctr1->new_highwatermark;
256 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
257 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
258 uptodateness_vector = NULL; /* TODO: map it */
261 mapping_ctr = &c->ctr6->mapping_ctr;
262 object_count = s->schema_part.object_count;
263 first_object = s->schema_part.first_object;
264 linked_attributes_count = c->ctr6->linked_attributes_count;
265 linked_attributes = c->ctr6->linked_attributes;
266 s_dsa->highwatermark = c->ctr6->new_highwatermark;
267 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
268 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
269 uptodateness_vector = c->ctr6->uptodateness_vector;
272 return NT_STATUS_INVALID_PARAMETER;
275 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
276 | DRSUAPI_DRS_INIT_SYNC
277 | DRSUAPI_DRS_PER_SYNC;
278 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
280 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
281 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
282 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
283 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
284 s_dsa->other_info->dns_name = tmp_dns_name;
286 schema_ldb = provision_get_schema(s, s->lp_ctx, &s->prefixmap_blob);
288 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. Will continue with local prefixMap\n"));
289 s->provision_schema = dsdb_get_schema(s->ldb, s);
291 s->provision_schema = dsdb_get_schema(schema_ldb, s);
292 ret = dsdb_reference_schema(s->ldb, s->provision_schema, false);
293 if (ret != LDB_SUCCESS) {
294 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
295 return NT_STATUS_UNSUCCESSFUL;
297 talloc_free(schema_ldb);
300 s->provision_schema->relax_OID_conversions = true;
302 /* Now convert the schema elements, using the schema we loaded locally */
303 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
304 struct dsdb_extended_replicated_object object;
305 TALLOC_CTX *tmp_ctx = talloc_new(s);
306 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
308 /* Convert the objects into LDB messages using the
309 * provision schema, and either the provision or DRS
310 * prefix map - it should not matter, as these are
311 * just schema objects, so the critical parts. At
312 * most we would mix up the mayContain etc for new
314 status = dsdb_convert_object_ex(s->ldb, s->provision_schema,
317 if (!W_ERROR_IS_OK(status)) {
318 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
320 /* Convert the schema from ldb_message format
321 * (OIDs as OID strings) into schema, using
322 * the remote prefixMap */
323 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_made_schema, object.msg);
324 if (!W_ERROR_IS_OK(status)) {
325 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
326 ldb_dn_get_linearized(object.msg->dn),
327 win_errstr(status)));
330 talloc_free(tmp_ctx);
333 /* attach the schema we just brought over DRS to the ldb, so we can use it in dsdb_convert_object_ex below */
334 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
335 if (ret != LDB_SUCCESS) {
336 DEBUG(0,("Failed to attach 1st pass schema from DRS.\n"));
337 return NT_STATUS_FOOBAR;
340 /* Now convert the schema elements again, using the schema we loaded over DRS */
341 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
342 struct dsdb_extended_replicated_object object;
343 TALLOC_CTX *tmp_ctx = talloc_new(s);
344 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
346 /* Convert the objects into LDB messages using the
347 * self_made_schema, and the DRS prefix map. We now
348 * know the full schema int->OID->name mapping, so we
349 * can get it right this time */
350 status = dsdb_convert_object_ex(s->ldb, s->self_made_schema,
353 if (!W_ERROR_IS_OK(status)) {
354 DEBUG(0,("ERROR: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
356 /* Convert the schema from ldb_message format
357 * (OIDs as OID strings) into schema, using
358 * the remote prefixMap, now that we know
359 * names for all the schema elements (from the
360 * first conversion) */
361 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_corrected_schema, object.msg);
362 if (!W_ERROR_IS_OK(status)) {
363 DEBUG(0,("ERROR: failed to convert object %s into a schema element: %s\n",
364 ldb_dn_get_linearized(object.msg->dn),
365 win_errstr(status)));
368 talloc_free(tmp_ctx);
371 /* We don't want to use the s->self_made_schema any more */
372 s->self_made_schema = NULL;
374 /* attach the schema we just brought over DRS to the ldb */
375 ret = dsdb_set_schema(s->ldb, s->self_corrected_schema);
376 if (ret != LDB_SUCCESS) {
377 DEBUG(0,("Failed to attach 2nd pass (corrected) schema from DRS.\n"));
378 return NT_STATUS_FOOBAR;
381 /* we don't want to access the self made schema anymore */
382 s->schema = s->self_corrected_schema;
383 s->self_corrected_schema = NULL;
385 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
386 status = dsdb_extended_replicated_objects_convert(s->ldb,
391 linked_attributes_count,
397 if (!W_ERROR_IS_OK(status)) {
398 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
399 return werror_to_ntstatus(status);
402 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
403 for (i=0; i < schema_objs->num_objects; i++) {
404 struct ldb_ldif ldif;
405 fprintf(stdout, "#\n");
406 ldif.changetype = LDB_CHANGETYPE_NONE;
407 ldif.msg = schema_objs->objects[i].msg;
408 ldb_ldif_write_file(s->ldb, stdout, &ldif);
409 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
413 status = dsdb_extended_replicated_objects_commit(s->ldb, schema_objs, &seq_num);
414 if (!W_ERROR_IS_OK(status)) {
415 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
416 return werror_to_ntstatus(status);
419 msg = ldb_msg_new(schema_objs);
420 NT_STATUS_HAVE_NO_MEMORY(msg);
421 msg->dn = schema_objs->partition_dn;
423 /* We must ensure a prefixMap has been written. Unlike other
424 * attributes (including schemaInfo), it is not replicated in
425 * the normal replication stream. We can use the one from
426 * s->prefixmap_blob because we operate with one, unchanging
427 * prefixMap for this entire operation. */
428 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
429 if (ret != LDB_SUCCESS) {
430 return NT_STATUS_FOOBAR;
432 /* We want to know if a prefixMap was written already, as it
433 * would mean that the above comment was not true, and we have
434 * somehow updated the prefixMap during this transaction */
435 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
437 ret = ldb_modify(s->ldb, msg);
438 if (ret != LDB_SUCCESS) {
439 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
440 return NT_STATUS_FOOBAR;
444 talloc_free(schema_objs);
446 /* We must set these up to ensure the replMetaData is written
447 * correctly, before our NTDS Settings entry is replicated */
448 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
450 DEBUG(0,("Failed to set cached ntds invocationId\n"));
451 return NT_STATUS_FOOBAR;
453 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
455 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
456 return NT_STATUS_FOOBAR;
459 s->schema = dsdb_get_schema(s->ldb, s);
461 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
462 return NT_STATUS_FOOBAR;
468 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
469 const struct libnet_BecomeDC_StoreChunk *c)
471 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
473 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
474 uint32_t nc_object_count;
475 uint32_t object_count;
476 struct drsuapi_DsReplicaObjectListItemEx *first_object;
477 struct drsuapi_DsReplicaObjectListItemEx *cur;
478 uint32_t nc_linked_attributes_count;
479 uint32_t linked_attributes_count;
480 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
482 switch (c->ctr_level) {
484 mapping_ctr = &c->ctr1->mapping_ctr;
485 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
486 object_count = c->ctr1->object_count;
487 first_object = c->ctr1->first_object;
488 nc_linked_attributes_count = 0;
489 linked_attributes_count = 0;
490 linked_attributes = NULL;
493 mapping_ctr = &c->ctr6->mapping_ctr;
494 nc_object_count = c->ctr6->nc_object_count;
495 object_count = c->ctr6->object_count;
496 first_object = c->ctr6->first_object;
497 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
498 linked_attributes_count = c->ctr6->linked_attributes_count;
499 linked_attributes = c->ctr6->linked_attributes;
502 return NT_STATUS_INVALID_PARAMETER;
505 if (nc_object_count) {
506 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
507 c->partition->nc.dn, object_count, nc_object_count,
508 linked_attributes_count, nc_linked_attributes_count));
510 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
511 c->partition->nc.dn, object_count, linked_attributes_count));
514 if (!s->self_made_schema) {
516 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
517 /* Put the DRS prefixmap aside for the schema we are
518 * about to load in the provision, and into the one we
519 * are making with the help of DRS */
521 mapping_ctr_without_schema_info = *mapping_ctr;
523 /* This strips off the 0xFF schema info from the end,
524 * because we don't want it in the blob */
525 if (mapping_ctr_without_schema_info.num_mappings > 0) {
526 mapping_ctr_without_schema_info.num_mappings--;
528 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
529 if (!W_ERROR_IS_OK(werr)) {
530 return werror_to_ntstatus(werr);
533 /* Set up two manually-constructed schema - the local
534 * schema from the provision will be used to build
535 * one, which will then in turn be used to build the
537 s->self_made_schema = dsdb_new_schema(s);
538 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
539 s->self_corrected_schema = dsdb_new_schema(s);
540 NT_STATUS_HAVE_NO_MEMORY(s->self_corrected_schema);
542 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
543 if (!W_ERROR_IS_OK(status)) {
544 return werror_to_ntstatus(status);
547 status = dsdb_load_prefixmap_from_drsuapi(s->self_corrected_schema, mapping_ctr);
548 if (!W_ERROR_IS_OK(status)) {
549 return werror_to_ntstatus(status);
552 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
553 if (!W_ERROR_IS_OK(status)) {
554 return werror_to_ntstatus(status);
558 if (!s->schema_part.first_object) {
559 s->schema_part.object_count = object_count;
560 s->schema_part.first_object = talloc_steal(s, first_object);
562 s->schema_part.object_count += object_count;
563 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
566 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
567 s->schema_part.last_object = cur;
569 if (!c->partition->more_data) {
570 return libnet_vampire_cb_apply_schema(s, c);
576 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
577 const struct libnet_BecomeDC_StoreChunk *c)
579 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
581 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
582 uint32_t nc_object_count;
583 uint32_t object_count;
584 struct drsuapi_DsReplicaObjectListItemEx *first_object;
585 uint32_t nc_linked_attributes_count;
586 uint32_t linked_attributes_count;
587 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
588 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
589 struct dsdb_extended_replicated_objects *objs;
590 struct repsFromTo1 *s_dsa;
595 s_dsa = talloc_zero(s, struct repsFromTo1);
596 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
597 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
598 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
600 switch (c->ctr_level) {
602 mapping_ctr = &c->ctr1->mapping_ctr;
603 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
604 object_count = c->ctr1->object_count;
605 first_object = c->ctr1->first_object;
606 nc_linked_attributes_count = 0;
607 linked_attributes_count = 0;
608 linked_attributes = NULL;
609 s_dsa->highwatermark = c->ctr1->new_highwatermark;
610 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
611 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
612 uptodateness_vector = NULL; /* TODO: map it */
615 mapping_ctr = &c->ctr6->mapping_ctr;
616 nc_object_count = c->ctr6->nc_object_count;
617 object_count = c->ctr6->object_count;
618 first_object = c->ctr6->first_object;
619 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
620 linked_attributes_count = c->ctr6->linked_attributes_count;
621 linked_attributes = c->ctr6->linked_attributes;
622 s_dsa->highwatermark = c->ctr6->new_highwatermark;
623 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
624 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
625 uptodateness_vector = c->ctr6->uptodateness_vector;
628 return NT_STATUS_INVALID_PARAMETER;
631 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
632 | DRSUAPI_DRS_INIT_SYNC
633 | DRSUAPI_DRS_PER_SYNC;
634 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
636 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
637 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
638 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
639 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
640 s_dsa->other_info->dns_name = tmp_dns_name;
642 /* we want to show a count per partition */
643 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
644 s->total_objects = 0;
645 talloc_free(s->last_partition);
646 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
648 s->total_objects += object_count;
650 if (nc_object_count) {
651 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
652 c->partition->nc.dn, s->total_objects, nc_object_count,
653 linked_attributes_count, nc_linked_attributes_count));
655 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
656 c->partition->nc.dn, s->total_objects, linked_attributes_count));
660 status = dsdb_extended_replicated_objects_convert(s->ldb,
665 linked_attributes_count,
671 if (!W_ERROR_IS_OK(status)) {
672 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
673 return werror_to_ntstatus(status);
676 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
677 for (i=0; i < objs->num_objects; i++) {
678 struct ldb_ldif ldif;
679 fprintf(stdout, "#\n");
680 ldif.changetype = LDB_CHANGETYPE_NONE;
681 ldif.msg = objs->objects[i].msg;
682 ldb_ldif_write_file(s->ldb, stdout, &ldif);
683 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
686 status = dsdb_extended_replicated_objects_commit(s->ldb,
688 if (!W_ERROR_IS_OK(status)) {
689 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
690 return werror_to_ntstatus(status);
696 for (i=0; i < linked_attributes_count; i++) {
697 const struct dsdb_attribute *sa;
699 if (!linked_attributes[i].identifier) {
700 return NT_STATUS_FOOBAR;
703 if (!linked_attributes[i].value.blob) {
704 return NT_STATUS_FOOBAR;
707 sa = dsdb_attribute_by_attributeID_id(s->schema,
708 linked_attributes[i].attid);
710 return NT_STATUS_FOOBAR;
713 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
714 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
715 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
717 linked_attributes[i].value.blob->data,
718 linked_attributes[i].value.blob->length);
725 static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
726 struct ldb_context *ldb,
727 const char *server_dn_str,
728 const char *netbios_name,
732 struct ldb_message *msg;
733 struct ldb_message_element *el;
734 struct ldb_dn *server_dn;
735 const char *dNSHostName = strlower_talloc(mem_ctx,
736 talloc_asprintf(mem_ctx,
740 msg = ldb_msg_new(mem_ctx);
742 return NT_STATUS_NO_MEMORY;
745 server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
747 return NT_STATUS_INTERNAL_ERROR;
751 ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
752 if (ret != LDB_SUCCESS) {
753 return NT_STATUS_INTERNAL_ERROR;
756 ret = ldb_msg_add_steal_string(msg,
758 talloc_asprintf(el->values, "%s", dNSHostName));
759 if (ret != LDB_SUCCESS) {
760 return NT_STATUS_INTERNAL_ERROR;
763 ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
764 if (ret != LDB_SUCCESS) {
765 DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
766 ldb_errstring(ldb)));
767 return NT_STATUS_INTERNAL_ERROR;
774 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
775 struct libnet_Vampire *r)
777 struct libnet_JoinDomain *join;
778 struct libnet_Replicate rep;
781 const char *account_name;
782 const char *netbios_name;
784 r->out.error_string = NULL;
786 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
788 return NT_STATUS_NO_MEMORY;
791 if (r->in.netbios_name != NULL) {
792 netbios_name = r->in.netbios_name;
794 netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
797 r->out.error_string = NULL;
798 return NT_STATUS_NO_MEMORY;
802 account_name = talloc_asprintf(join, "%s$", netbios_name);
805 r->out.error_string = NULL;
806 return NT_STATUS_NO_MEMORY;
809 /* Re-use the domain we are joining as the domain for the user
810 * to be authenticated with, unless they specified
812 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
814 join->in.domain_name = r->in.domain_name;
815 join->in.account_name = account_name;
816 join->in.netbios_name = netbios_name;
817 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
818 join->in.acct_type = ACB_WSTRUST;
819 join->in.recreate_account = false;
820 status = libnet_JoinDomain(ctx, join, join);
821 if (!NT_STATUS_IS_OK(status)) {
822 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
827 rep.in.domain_name = join->out.domain_name;
828 rep.in.netbios_name = netbios_name;
829 rep.in.targetdir = r->in.targetdir;
830 rep.in.domain_sid = join->out.domain_sid;
831 rep.in.realm = join->out.realm;
832 rep.in.server = join->out.samr_binding->host;
833 rep.in.join_password = join->out.join_password;
834 rep.in.kvno = join->out.kvno;
836 status = libnet_Replicate(ctx, mem_ctx, &rep);
838 r->out.domain_sid = join->out.domain_sid;
839 r->out.domain_name = join->out.domain_name;
840 r->out.error_string = rep.out.error_string;
847 NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
848 struct libnet_Replicate *r)
850 struct provision_store_self_join_settings *set_secrets;
851 struct libnet_BecomeDC b;
852 struct libnet_vampire_cb_state *s;
853 struct ldb_message *msg;
854 const char *error_string;
858 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
859 const char *account_name;
860 const char *netbios_name;
862 r->out.error_string = NULL;
864 netbios_name = r->in.netbios_name;
865 account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
867 talloc_free(tmp_ctx);
868 r->out.error_string = NULL;
869 return NT_STATUS_NO_MEMORY;
872 /* Re-use the domain we are joining as the domain for the user
873 * to be authenticated with, unless they specified
875 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
877 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
878 netbios_name, r->in.domain_name, r->in.realm,
881 return NT_STATUS_NO_MEMORY;
883 talloc_steal(s, tmp_ctx);
888 * We now know the domain and realm for sure - if they didn't
889 * put one on the command line, use this for the rest of the
891 cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
892 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
894 /* Now set these values into the smb.conf - we probably had
895 * empty or useless defaults here from whatever smb.conf we
897 lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
898 lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
900 b.in.domain_dns_name = r->in.realm;
901 b.in.domain_netbios_name = r->in.domain_name;
902 b.in.domain_sid = r->in.domain_sid;
903 b.in.source_dsa_address = r->in.server;
904 b.in.dest_dsa_netbios_name = netbios_name;
906 b.in.callbacks.private_data = s;
907 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
908 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
909 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
910 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
911 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
913 b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
915 status = libnet_BecomeDC(ctx, s, &b);
916 if (!NT_STATUS_IS_OK(status)) {
917 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
922 msg = ldb_msg_new(s);
924 printf("ldb_msg_new() failed\n");
926 return NT_STATUS_NO_MEMORY;
928 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
930 printf("ldb_msg_new(@ROOTDSE) failed\n");
932 return NT_STATUS_NO_MEMORY;
935 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
936 if (ldb_ret != LDB_SUCCESS) {
937 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
939 return NT_STATUS_NO_MEMORY;
942 for (i=0; i < msg->num_elements; i++) {
943 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
946 printf("mark ROOTDSE with isSynchronized=TRUE\n");
947 ldb_ret = ldb_modify(s->ldb, msg);
948 if (ldb_ret != LDB_SUCCESS) {
949 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
951 return NT_STATUS_INTERNAL_DB_ERROR;
953 /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
954 * the attribute appears on the original DC after replication
956 status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
957 if (!NT_STATUS_IS_OK(status)) {
958 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
962 /* prepare the transaction - this prepares to commit all the changes in
963 the ldb from the whole vampire. Note that this
964 triggers the writing of the linked attribute backlinks.
966 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
967 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
968 return NT_STATUS_INTERNAL_DB_ERROR;
971 set_secrets = talloc(s, struct provision_store_self_join_settings);
973 r->out.error_string = NULL;
975 return NT_STATUS_NO_MEMORY;
978 ZERO_STRUCTP(set_secrets);
979 set_secrets->domain_name = r->in.domain_name;
980 set_secrets->realm = r->in.realm;
981 set_secrets->netbios_name = netbios_name;
982 set_secrets->secure_channel_type = SEC_CHAN_BDC;
983 set_secrets->machine_password = r->in.join_password;
984 set_secrets->key_version_number = r->in.kvno;
985 set_secrets->domain_sid = r->in.domain_sid;
987 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
988 if (!NT_STATUS_IS_OK(status)) {
989 r->out.error_string = talloc_steal(mem_ctx, error_string);
994 /* commit the transaction now we know the secrets were written
997 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
998 printf("Failed to commit vampire transaction\n");
999 return NT_STATUS_INTERNAL_DB_ERROR;
1004 return NT_STATUS_OK;