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"
37 #include "lib/ldb_wrap.h"
38 #include "auth/auth.h"
39 #include "param/param.h"
40 #include "param/provision.h"
41 #include "libcli/security/dom_sid.h"
44 List of tasks vampire.py must perform:
46 - but don't write the secrets.ldb
47 - results for this should be enough to handle the provision
48 - if vampire method is samsync
49 - Provision using these results
50 - do we still want to support this NT4 technology?
51 - Start samsync with libnet code
52 - provision in the callback
53 - Write out the secrets database, using the code from libnet_Join
56 struct vampire_state {
57 const char *netbios_name;
58 struct libnet_JoinDomain *join;
59 struct cli_credentials *machine_account;
60 struct dsdb_schema *self_made_schema;
61 const struct dsdb_schema *schema;
63 struct ldb_context *ldb;
66 uint32_t object_count;
67 struct drsuapi_DsReplicaObjectListItemEx *first_object;
68 struct drsuapi_DsReplicaObjectListItemEx *last_object;
71 const char *targetdir;
73 struct loadparm_context *lp_ctx;
74 struct tevent_context *event_ctx;
75 unsigned total_objects;
79 static NTSTATUS vampire_prepare_db(void *private_data,
80 const struct libnet_BecomeDC_PrepareDB *p)
82 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
83 struct provision_settings settings;
84 struct provision_result result;
87 ZERO_STRUCT(settings);
88 settings.site_name = p->dest_dsa->site_name;
89 settings.root_dn_str = p->forest->root_dn_str;
90 settings.domain_dn_str = p->domain->dn_str;
91 settings.config_dn_str = p->forest->config_dn_str;
92 settings.schema_dn_str = p->forest->schema_dn_str;
93 settings.netbios_name = p->dest_dsa->netbios_name;
94 settings.realm = s->join->out.realm;
95 settings.domain = s->join->out.domain_name;
96 settings.server_dn_str = p->dest_dsa->server_dn_str;
97 settings.machine_password = generate_random_str(s, 16);
98 settings.targetdir = s->targetdir;
100 status = provision_bare(s, s->lp_ctx, &settings, &result);
102 if (!NT_STATUS_IS_OK(status)) {
106 s->ldb = result.samdb;
107 s->lp_ctx = result.lp_ctx;
109 /* wrap the entire vapire operation in a transaction. This
110 isn't just cosmetic - we use this to ensure that linked
111 attribute back links are added at the end by relying on a
112 transaction commit hook in the linked attributes module. We
113 need to do this as the order of objects coming from the
114 server is not sufficiently deterministic to know that the
115 record that a backlink needs to be created in has itself
116 been created before the object containing the forward link
117 has come over the wire */
118 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
119 return NT_STATUS_FOOBAR;
127 static NTSTATUS vampire_check_options(void *private_data,
128 const struct libnet_BecomeDC_CheckOptions *o)
130 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
132 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
134 o->domain->netbios_name, o->domain->dns_name));
136 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
137 o->source_dsa->dns_name, o->source_dsa->site_name));
139 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
140 "\tschema object_version[%u]\n"
141 "\tdomain behavior_version[%u]\n"
142 "\tdomain w2k3_update_revision[%u]\n",
143 o->forest->crossref_behavior_version,
144 o->forest->schema_object_version,
145 o->domain->behavior_version,
146 o->domain->w2k3_update_revision));
151 static NTSTATUS vampire_apply_schema(struct vampire_state *s,
152 const struct libnet_BecomeDC_StoreChunk *c)
155 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
156 uint32_t object_count;
157 struct drsuapi_DsReplicaObjectListItemEx *first_object;
158 struct drsuapi_DsReplicaObjectListItemEx *cur;
159 uint32_t linked_attributes_count;
160 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
161 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
162 struct dsdb_extended_replicated_objects *objs;
163 struct repsFromTo1 *s_dsa;
165 struct ldb_message *msg;
166 struct ldb_val prefixMap_val;
167 struct ldb_message_element *prefixMap_el;
168 struct ldb_val schemaInfo_val;
174 DEBUG(0,("Analyze and apply schema objects\n"));
176 s_dsa = talloc_zero(s, struct repsFromTo1);
177 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
178 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
179 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
181 switch (c->ctr_level) {
183 mapping_ctr = &c->ctr1->mapping_ctr;
184 object_count = s->schema_part.object_count;
185 first_object = s->schema_part.first_object;
186 linked_attributes_count = 0;
187 linked_attributes = NULL;
188 s_dsa->highwatermark = c->ctr1->new_highwatermark;
189 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
190 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
191 uptodateness_vector = NULL; /* TODO: map it */
194 mapping_ctr = &c->ctr6->mapping_ctr;
195 object_count = s->schema_part.object_count;
196 first_object = s->schema_part.first_object;
197 linked_attributes_count = c->ctr6->linked_attributes_count;
198 linked_attributes = c->ctr6->linked_attributes;
199 s_dsa->highwatermark = c->ctr6->new_highwatermark;
200 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
201 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
202 uptodateness_vector = c->ctr6->uptodateness_vector;
205 return NT_STATUS_INVALID_PARAMETER;
208 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
209 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
210 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
211 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
213 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
214 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
215 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
216 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
217 s_dsa->other_info->dns_name = tmp_dns_name;
219 for (cur = first_object; cur; cur = cur->next_object) {
220 bool is_attr = false;
221 bool is_class = false;
223 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
224 struct drsuapi_DsReplicaAttribute *a;
226 const char *oid = NULL;
228 a = &cur->object.attribute_ctr.attributes[i];
229 status = dsdb_schema_pfm_oid_from_attid(s->self_made_schema->prefixmap,
231 if (!W_ERROR_IS_OK(status)) {
232 return werror_to_ntstatus(status);
236 case DRSUAPI_ATTRIBUTE_objectClass:
237 for (j=0; j < a->value_ctr.num_values; j++) {
238 uint32_t val = 0xFFFFFFFF;
240 if (a->value_ctr.values[j].blob
241 && a->value_ctr.values[j].blob->length == 4) {
242 val = IVAL(a->value_ctr.values[j].blob->data,0);
245 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
248 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
260 struct dsdb_attribute *sa;
262 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
263 NT_STATUS_HAVE_NO_MEMORY(sa);
265 status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
266 if (!W_ERROR_IS_OK(status)) {
267 return werror_to_ntstatus(status);
270 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
274 struct dsdb_class *sc;
276 sc = talloc_zero(s->self_made_schema, struct dsdb_class);
277 NT_STATUS_HAVE_NO_MEMORY(sc);
279 status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
280 if (!W_ERROR_IS_OK(status)) {
281 return werror_to_ntstatus(status);
284 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
288 /* attach the schema to the ldb */
289 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
290 if (ret != LDB_SUCCESS) {
291 return NT_STATUS_FOOBAR;
293 /* we don't want to access the self made schema anymore */
294 s->self_made_schema = NULL;
295 s->schema = dsdb_get_schema(s->ldb);
297 status = dsdb_extended_replicated_objects_commit(s->ldb,
302 linked_attributes_count,
308 if (!W_ERROR_IS_OK(status)) {
309 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
310 return werror_to_ntstatus(status);
313 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
314 for (i=0; i < objs->num_objects; i++) {
315 struct ldb_ldif ldif;
316 fprintf(stdout, "#\n");
317 ldif.changetype = LDB_CHANGETYPE_NONE;
318 ldif.msg = objs->objects[i].msg;
319 ldb_ldif_write_file(s->ldb, stdout, &ldif);
320 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
324 msg = ldb_msg_new(objs);
325 NT_STATUS_HAVE_NO_MEMORY(msg);
326 msg->dn = objs->partition_dn;
328 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
329 if (!W_ERROR_IS_OK(status)) {
330 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
331 return werror_to_ntstatus(status);
334 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
335 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
336 if (ret != LDB_SUCCESS) {
337 return NT_STATUS_FOOBAR;
339 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
341 ret = ldb_modify(s->ldb, msg);
342 if (ret != LDB_SUCCESS) {
343 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
344 return NT_STATUS_FOOBAR;
350 /* We must set these up to ensure the replMetaData is written
351 * correctly, before our NTDS Settings entry is replicated */
352 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
354 DEBUG(0,("Failed to set cached ntds invocationId\n"));
355 return NT_STATUS_FOOBAR;
357 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
359 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
360 return NT_STATUS_FOOBAR;
363 s->schema = dsdb_get_schema(s->ldb);
365 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
366 return NT_STATUS_FOOBAR;
372 static NTSTATUS vampire_schema_chunk(void *private_data,
373 const struct libnet_BecomeDC_StoreChunk *c)
375 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
377 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
378 uint32_t nc_object_count;
379 uint32_t object_count;
380 struct drsuapi_DsReplicaObjectListItemEx *first_object;
381 struct drsuapi_DsReplicaObjectListItemEx *cur;
382 uint32_t nc_linked_attributes_count;
383 uint32_t linked_attributes_count;
384 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
386 switch (c->ctr_level) {
388 mapping_ctr = &c->ctr1->mapping_ctr;
389 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
390 object_count = c->ctr1->object_count;
391 first_object = c->ctr1->first_object;
392 nc_linked_attributes_count = 0;
393 linked_attributes_count = 0;
394 linked_attributes = NULL;
397 mapping_ctr = &c->ctr6->mapping_ctr;
398 nc_object_count = c->ctr6->nc_object_count;
399 object_count = c->ctr6->object_count;
400 first_object = c->ctr6->first_object;
401 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
402 linked_attributes_count = c->ctr6->linked_attributes_count;
403 linked_attributes = c->ctr6->linked_attributes;
406 return NT_STATUS_INVALID_PARAMETER;
409 if (nc_object_count) {
410 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
411 c->partition->nc.dn, object_count, nc_object_count,
412 linked_attributes_count, nc_linked_attributes_count));
414 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
415 c->partition->nc.dn, object_count, linked_attributes_count));
419 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
421 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
423 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
424 if (!W_ERROR_IS_OK(status)) {
425 return werror_to_ntstatus(status);
428 s->schema = s->self_made_schema;
430 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->schema->prefixmap, mapping_ctr);
431 if (!W_ERROR_IS_OK(status)) {
432 return werror_to_ntstatus(status);
436 if (!s->schema_part.first_object) {
437 s->schema_part.object_count = object_count;
438 s->schema_part.first_object = talloc_steal(s, first_object);
440 s->schema_part.object_count += object_count;
441 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
444 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
445 s->schema_part.last_object = cur;
447 if (!c->partition->more_data) {
448 return vampire_apply_schema(s, c);
454 static NTSTATUS vampire_store_chunk(void *private_data,
455 const struct libnet_BecomeDC_StoreChunk *c)
457 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
459 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
460 uint32_t nc_object_count;
461 uint32_t object_count;
462 struct drsuapi_DsReplicaObjectListItemEx *first_object;
463 uint32_t nc_linked_attributes_count;
464 uint32_t linked_attributes_count;
465 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
466 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
467 struct dsdb_extended_replicated_objects *objs;
468 struct repsFromTo1 *s_dsa;
473 s_dsa = talloc_zero(s, struct repsFromTo1);
474 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
475 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
476 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
478 switch (c->ctr_level) {
480 mapping_ctr = &c->ctr1->mapping_ctr;
481 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
482 object_count = c->ctr1->object_count;
483 first_object = c->ctr1->first_object;
484 nc_linked_attributes_count = 0;
485 linked_attributes_count = 0;
486 linked_attributes = NULL;
487 s_dsa->highwatermark = c->ctr1->new_highwatermark;
488 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
489 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
490 uptodateness_vector = NULL; /* TODO: map it */
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;
500 s_dsa->highwatermark = c->ctr6->new_highwatermark;
501 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
502 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
503 uptodateness_vector = c->ctr6->uptodateness_vector;
506 return NT_STATUS_INVALID_PARAMETER;
509 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
510 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
511 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
512 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
514 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
515 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
516 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
517 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
518 s_dsa->other_info->dns_name = tmp_dns_name;
520 /* we want to show a count per partition */
521 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
522 s->total_objects = 0;
523 talloc_free(s->last_partition);
524 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
526 s->total_objects += object_count;
528 if (nc_object_count) {
529 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
530 c->partition->nc.dn, s->total_objects, nc_object_count,
531 linked_attributes_count, nc_linked_attributes_count));
533 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
534 c->partition->nc.dn, s->total_objects, linked_attributes_count));
538 status = dsdb_extended_replicated_objects_commit(s->ldb,
543 linked_attributes_count,
549 if (!W_ERROR_IS_OK(status)) {
550 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
551 return werror_to_ntstatus(status);
554 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
555 for (i=0; i < objs->num_objects; i++) {
556 struct ldb_ldif ldif;
557 fprintf(stdout, "#\n");
558 ldif.changetype = LDB_CHANGETYPE_NONE;
559 ldif.msg = objs->objects[i].msg;
560 ldb_ldif_write_file(s->ldb, stdout, &ldif);
561 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
567 for (i=0; i < linked_attributes_count; i++) {
568 const struct dsdb_attribute *sa;
570 if (!linked_attributes[i].identifier) {
571 return NT_STATUS_FOOBAR;
574 if (!linked_attributes[i].value.blob) {
575 return NT_STATUS_FOOBAR;
578 sa = dsdb_attribute_by_attributeID_id(s->schema,
579 linked_attributes[i].attid);
581 return NT_STATUS_FOOBAR;
584 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
585 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
586 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
588 linked_attributes[i].value.blob->data,
589 linked_attributes[i].value.blob->length);
596 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
597 struct libnet_Vampire *r)
599 struct libnet_JoinDomain *join;
600 struct provision_store_self_join_settings *set_secrets;
601 struct libnet_BecomeDC b;
602 struct vampire_state *s;
603 struct ldb_message *msg;
604 const char *error_string;
609 const char *account_name;
610 const char *netbios_name;
612 r->out.error_string = NULL;
614 s = talloc_zero(mem_ctx, struct vampire_state);
616 return NT_STATUS_NO_MEMORY;
619 s->lp_ctx = ctx->lp_ctx;
620 s->event_ctx = ctx->event_ctx;
622 join = talloc_zero(s, struct libnet_JoinDomain);
624 return NT_STATUS_NO_MEMORY;
627 if (r->in.netbios_name != NULL) {
628 netbios_name = r->in.netbios_name;
630 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
632 r->out.error_string = NULL;
634 return NT_STATUS_NO_MEMORY;
638 account_name = talloc_asprintf(join, "%s$", netbios_name);
640 r->out.error_string = NULL;
642 return NT_STATUS_NO_MEMORY;
645 join->in.domain_name = r->in.domain_name;
646 join->in.account_name = account_name;
647 join->in.netbios_name = netbios_name;
648 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
649 join->in.acct_type = ACB_WSTRUST;
650 join->in.recreate_account = false;
651 status = libnet_JoinDomain(ctx, join, join);
652 if (!NT_STATUS_IS_OK(status)) {
653 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
660 s->targetdir = r->in.targetdir;
663 b.in.domain_dns_name = join->out.realm;
664 b.in.domain_netbios_name = join->out.domain_name;
665 b.in.domain_sid = join->out.domain_sid;
666 b.in.source_dsa_address = join->out.samr_binding->host;
667 b.in.dest_dsa_netbios_name = netbios_name;
669 b.in.callbacks.private_data = s;
670 b.in.callbacks.check_options = vampire_check_options;
671 b.in.callbacks.prepare_db = vampire_prepare_db;
672 b.in.callbacks.schema_chunk = vampire_schema_chunk;
673 b.in.callbacks.config_chunk = vampire_store_chunk;
674 b.in.callbacks.domain_chunk = vampire_store_chunk;
676 status = libnet_BecomeDC(ctx, s, &b);
677 if (!NT_STATUS_IS_OK(status)) {
678 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
683 msg = ldb_msg_new(s);
685 printf("ldb_msg_new() failed\n");
687 return NT_STATUS_NO_MEMORY;
689 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
691 printf("ldb_msg_new(@ROOTDSE) failed\n");
693 return NT_STATUS_NO_MEMORY;
696 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
697 if (ldb_ret != LDB_SUCCESS) {
698 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
700 return NT_STATUS_NO_MEMORY;
703 for (i=0; i < msg->num_elements; i++) {
704 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
707 printf("mark ROOTDSE with isSynchronized=TRUE\n");
708 ldb_ret = ldb_modify(s->ldb, msg);
709 if (ldb_ret != LDB_SUCCESS) {
710 printf("ldb_modify() failed: %d\n", ldb_ret);
712 return NT_STATUS_INTERNAL_DB_ERROR;
715 /* prepare the transaction - this prepares to commit all the changes in
716 the ldb from the whole vampire. Note that this
717 triggers the writing of the linked attribute backlinks.
719 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
720 printf("Failed to prepare_commit vampire transaction\n");
721 return NT_STATUS_INTERNAL_DB_ERROR;
724 set_secrets = talloc(s, struct provision_store_self_join_settings);
726 r->out.error_string = NULL;
728 return NT_STATUS_NO_MEMORY;
731 ZERO_STRUCTP(set_secrets);
732 set_secrets->domain_name = join->out.domain_name;
733 set_secrets->realm = join->out.realm;
734 set_secrets->account_name = account_name;
735 set_secrets->netbios_name = netbios_name;
736 set_secrets->secure_channel_type = SEC_CHAN_BDC;
737 set_secrets->machine_password = join->out.join_password;
738 set_secrets->key_version_number = join->out.kvno;
739 set_secrets->domain_sid = join->out.domain_sid;
741 status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
742 if (!NT_STATUS_IS_OK(status)) {
743 r->out.error_string = talloc_steal(mem_ctx, error_string);
748 r->out.domain_name = talloc_steal(r, join->out.domain_name);
749 r->out.domain_sid = dom_sid_dup(r, join->out.domain_sid);
751 /* commit the transaction now we know the secrets were written
754 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
755 printf("Failed to commit vampire transaction\n");
756 return NT_STATUS_INTERNAL_DB_ERROR;