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 "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;
62 struct dsdb_schema *self_made_schema;
63 const struct dsdb_schema *schema;
65 struct ldb_context *ldb;
68 uint32_t object_count;
69 struct drsuapi_DsReplicaObjectListItemEx *first_object;
70 struct drsuapi_DsReplicaObjectListItemEx *last_object;
73 const char *targetdir;
75 struct loadparm_context *lp_ctx;
76 struct tevent_context *event_ctx;
77 unsigned total_objects;
81 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
82 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
83 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
84 const char *netbios_name, const char *domain_name, const char *realm,
85 const char *targetdir)
87 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
93 s->event_ctx = event_ctx;
94 s->netbios_name = netbios_name;
95 s->domain_name = domain_name;
97 s->targetdir = targetdir;
101 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
103 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
107 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
109 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
110 return state->lp_ctx;
113 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
114 const struct libnet_BecomeDC_PrepareDB *p)
116 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
117 struct provision_settings settings;
118 struct provision_result result;
121 ZERO_STRUCT(settings);
122 settings.site_name = p->dest_dsa->site_name;
123 settings.root_dn_str = p->forest->root_dn_str;
124 settings.domain_dn_str = p->domain->dn_str;
125 settings.config_dn_str = p->forest->config_dn_str;
126 settings.schema_dn_str = p->forest->schema_dn_str;
127 settings.netbios_name = p->dest_dsa->netbios_name;
128 settings.realm = s->realm;
129 settings.domain = s->domain_name;
130 settings.server_dn_str = p->dest_dsa->server_dn_str;
131 settings.machine_password = generate_random_password(s, 16, 255);
132 settings.targetdir = s->targetdir;
134 status = provision_bare(s, s->lp_ctx, &settings, &result);
136 if (!NT_STATUS_IS_OK(status)) {
140 s->ldb = talloc_steal(s, result.samdb);
141 s->lp_ctx = talloc_steal(s, result.lp_ctx);
143 /* wrap the entire vapire operation in a transaction. This
144 isn't just cosmetic - we use this to ensure that linked
145 attribute back links are added at the end by relying on a
146 transaction commit hook in the linked attributes module. We
147 need to do this as the order of objects coming from the
148 server is not sufficiently deterministic to know that the
149 record that a backlink needs to be created in has itself
150 been created before the object containing the forward link
151 has come over the wire */
152 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
153 return NT_STATUS_FOOBAR;
161 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
162 const struct libnet_BecomeDC_CheckOptions *o)
164 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
166 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
168 o->domain->netbios_name, o->domain->dns_name));
170 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
171 o->source_dsa->dns_name, o->source_dsa->site_name));
173 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
174 "\tschema object_version[%u]\n"
175 "\tdomain behavior_version[%u]\n"
176 "\tdomain w2k3_update_revision[%u]\n",
177 o->forest->crossref_behavior_version,
178 o->forest->schema_object_version,
179 o->domain->behavior_version,
180 o->domain->w2k3_update_revision));
185 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
186 const struct libnet_BecomeDC_StoreChunk *c)
189 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
190 uint32_t object_count;
191 struct drsuapi_DsReplicaObjectListItemEx *first_object;
192 uint32_t linked_attributes_count;
193 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
194 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
195 struct dsdb_extended_replicated_objects *schema_objs_1, *schema_objs_2;
196 struct repsFromTo1 *s_dsa;
198 struct ldb_message *msg;
199 struct ldb_val prefixMap_val;
200 struct ldb_message_element *prefixMap_el;
201 struct ldb_val schemaInfo_val;
207 DEBUG(0,("Analyze and apply schema objects\n"));
209 s_dsa = talloc_zero(s, struct repsFromTo1);
210 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
211 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
212 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
214 switch (c->ctr_level) {
216 mapping_ctr = &c->ctr1->mapping_ctr;
217 object_count = s->schema_part.object_count;
218 first_object = s->schema_part.first_object;
219 linked_attributes_count = 0;
220 linked_attributes = NULL;
221 s_dsa->highwatermark = c->ctr1->new_highwatermark;
222 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
223 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
224 uptodateness_vector = NULL; /* TODO: map it */
227 mapping_ctr = &c->ctr6->mapping_ctr;
228 object_count = s->schema_part.object_count;
229 first_object = s->schema_part.first_object;
230 linked_attributes_count = c->ctr6->linked_attributes_count;
231 linked_attributes = c->ctr6->linked_attributes;
232 s_dsa->highwatermark = c->ctr6->new_highwatermark;
233 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
234 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
235 uptodateness_vector = c->ctr6->uptodateness_vector;
238 return NT_STATUS_INVALID_PARAMETER;
241 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
242 | DRSUAPI_DRS_INIT_SYNC
243 | DRSUAPI_DRS_PER_SYNC;
244 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
246 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
247 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
248 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
249 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
250 s_dsa->other_info->dns_name = tmp_dns_name;
252 /* Now convert the schema elements again, using the schema we just imported */
253 status = dsdb_extended_replicated_objects_convert(s->ldb,
258 linked_attributes_count,
264 if (!W_ERROR_IS_OK(status)) {
265 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
266 return werror_to_ntstatus(status);
269 for (i=0; i < schema_objs_1->num_objects; i++) {
270 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_made_schema, schema_objs_1->objects[i].msg);
271 if (!W_ERROR_IS_OK(status)) {
272 DEBUG(0,("Failed to convert object %s into a schema element: %s\n",
273 ldb_dn_get_linearized(schema_objs_1->objects[i].msg->dn),
274 win_errstr(status)));
275 return werror_to_ntstatus(status);
278 /* We don't need the first conversion of the schema any more */
279 talloc_free(schema_objs_1);
281 /* attach the schema we just brought over DRS to the ldb */
282 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
283 if (ret != LDB_SUCCESS) {
284 DEBUG(0,("Failed to attach schema from DRS.\n"));
285 return NT_STATUS_FOOBAR;
288 /* we don't want to access the self made schema anymore */
289 s->schema = s->self_made_schema;
290 s->self_made_schema = NULL;
292 /* Now convert the schema elements again, using the schema we just imported - we do this
293 'just in case' the schema in our LDIF was wrong, but correct enough to read a valid schema */
294 status = dsdb_extended_replicated_objects_convert(s->ldb,
299 linked_attributes_count,
305 if (!W_ERROR_IS_OK(status)) {
306 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
307 return werror_to_ntstatus(status);
310 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
311 for (i=0; i < schema_objs_2->num_objects; i++) {
312 struct ldb_ldif ldif;
313 fprintf(stdout, "#\n");
314 ldif.changetype = LDB_CHANGETYPE_NONE;
315 ldif.msg = schema_objs_2->objects[i].msg;
316 ldb_ldif_write_file(s->ldb, stdout, &ldif);
317 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs_2->objects[i].meta_data);
321 status = dsdb_extended_replicated_objects_commit(s->ldb, schema_objs_2, &seq_num);
322 if (!W_ERROR_IS_OK(status)) {
323 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
324 return werror_to_ntstatus(status);
327 msg = ldb_msg_new(schema_objs_2);
328 NT_STATUS_HAVE_NO_MEMORY(msg);
329 msg->dn = schema_objs_2->partition_dn;
331 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
332 if (!W_ERROR_IS_OK(status)) {
333 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
334 return werror_to_ntstatus(status);
337 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
338 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
339 if (ret != LDB_SUCCESS) {
340 return NT_STATUS_FOOBAR;
342 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
344 ret = ldb_modify(s->ldb, msg);
345 if (ret != LDB_SUCCESS) {
346 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_strerror(ret)));
347 return NT_STATUS_FOOBAR;
351 talloc_free(schema_objs_2);
353 /* We must set these up to ensure the replMetaData is written
354 * correctly, before our NTDS Settings entry is replicated */
355 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
357 DEBUG(0,("Failed to set cached ntds invocationId\n"));
358 return NT_STATUS_FOOBAR;
360 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
362 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
363 return NT_STATUS_FOOBAR;
366 s->schema = dsdb_get_schema(s->ldb, s);
368 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
369 return NT_STATUS_FOOBAR;
375 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
376 const struct libnet_BecomeDC_StoreChunk *c)
378 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
380 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
381 uint32_t nc_object_count;
382 uint32_t object_count;
383 struct drsuapi_DsReplicaObjectListItemEx *first_object;
384 struct drsuapi_DsReplicaObjectListItemEx *cur;
385 uint32_t nc_linked_attributes_count;
386 uint32_t linked_attributes_count;
387 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
389 switch (c->ctr_level) {
391 mapping_ctr = &c->ctr1->mapping_ctr;
392 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
393 object_count = c->ctr1->object_count;
394 first_object = c->ctr1->first_object;
395 nc_linked_attributes_count = 0;
396 linked_attributes_count = 0;
397 linked_attributes = NULL;
400 mapping_ctr = &c->ctr6->mapping_ctr;
401 nc_object_count = c->ctr6->nc_object_count;
402 object_count = c->ctr6->object_count;
403 first_object = c->ctr6->first_object;
404 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
405 linked_attributes_count = c->ctr6->linked_attributes_count;
406 linked_attributes = c->ctr6->linked_attributes;
409 return NT_STATUS_INVALID_PARAMETER;
412 if (nc_object_count) {
413 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
414 c->partition->nc.dn, object_count, nc_object_count,
415 linked_attributes_count, nc_linked_attributes_count));
417 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
418 c->partition->nc.dn, object_count, linked_attributes_count));
422 s->self_made_schema = dsdb_new_schema(s);
424 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
426 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
427 if (!W_ERROR_IS_OK(status)) {
428 return werror_to_ntstatus(status);
431 s->schema = s->self_made_schema;
433 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->schema->prefixmap, mapping_ctr);
434 if (!W_ERROR_IS_OK(status)) {
435 return werror_to_ntstatus(status);
439 if (!s->schema_part.first_object) {
440 s->schema_part.object_count = object_count;
441 s->schema_part.first_object = talloc_steal(s, first_object);
443 s->schema_part.object_count += object_count;
444 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
447 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
448 s->schema_part.last_object = cur;
450 if (!c->partition->more_data) {
451 return libnet_vampire_cb_apply_schema(s, c);
457 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
458 const struct libnet_BecomeDC_StoreChunk *c)
460 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
462 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
463 uint32_t nc_object_count;
464 uint32_t object_count;
465 struct drsuapi_DsReplicaObjectListItemEx *first_object;
466 uint32_t nc_linked_attributes_count;
467 uint32_t linked_attributes_count;
468 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
469 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
470 struct dsdb_extended_replicated_objects *objs;
471 struct repsFromTo1 *s_dsa;
476 s_dsa = talloc_zero(s, struct repsFromTo1);
477 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
478 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
479 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
481 switch (c->ctr_level) {
483 mapping_ctr = &c->ctr1->mapping_ctr;
484 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
485 object_count = c->ctr1->object_count;
486 first_object = c->ctr1->first_object;
487 nc_linked_attributes_count = 0;
488 linked_attributes_count = 0;
489 linked_attributes = NULL;
490 s_dsa->highwatermark = c->ctr1->new_highwatermark;
491 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
492 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
493 uptodateness_vector = NULL; /* TODO: map it */
496 mapping_ctr = &c->ctr6->mapping_ctr;
497 nc_object_count = c->ctr6->nc_object_count;
498 object_count = c->ctr6->object_count;
499 first_object = c->ctr6->first_object;
500 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
501 linked_attributes_count = c->ctr6->linked_attributes_count;
502 linked_attributes = c->ctr6->linked_attributes;
503 s_dsa->highwatermark = c->ctr6->new_highwatermark;
504 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
505 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
506 uptodateness_vector = c->ctr6->uptodateness_vector;
509 return NT_STATUS_INVALID_PARAMETER;
512 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
513 | DRSUAPI_DRS_INIT_SYNC
514 | DRSUAPI_DRS_PER_SYNC;
515 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
517 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
518 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
519 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
520 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
521 s_dsa->other_info->dns_name = tmp_dns_name;
523 /* we want to show a count per partition */
524 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
525 s->total_objects = 0;
526 talloc_free(s->last_partition);
527 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
529 s->total_objects += object_count;
531 if (nc_object_count) {
532 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
533 c->partition->nc.dn, s->total_objects, nc_object_count,
534 linked_attributes_count, nc_linked_attributes_count));
536 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
537 c->partition->nc.dn, s->total_objects, linked_attributes_count));
541 status = dsdb_extended_replicated_objects_convert(s->ldb,
546 linked_attributes_count,
552 if (!W_ERROR_IS_OK(status)) {
553 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
554 return werror_to_ntstatus(status);
557 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
558 for (i=0; i < objs->num_objects; i++) {
559 struct ldb_ldif ldif;
560 fprintf(stdout, "#\n");
561 ldif.changetype = LDB_CHANGETYPE_NONE;
562 ldif.msg = objs->objects[i].msg;
563 ldb_ldif_write_file(s->ldb, stdout, &ldif);
564 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
567 status = dsdb_extended_replicated_objects_commit(s->ldb,
569 if (!W_ERROR_IS_OK(status)) {
570 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
571 return werror_to_ntstatus(status);
577 for (i=0; i < linked_attributes_count; i++) {
578 const struct dsdb_attribute *sa;
580 if (!linked_attributes[i].identifier) {
581 return NT_STATUS_FOOBAR;
584 if (!linked_attributes[i].value.blob) {
585 return NT_STATUS_FOOBAR;
588 sa = dsdb_attribute_by_attributeID_id(s->schema,
589 linked_attributes[i].attid);
591 return NT_STATUS_FOOBAR;
594 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
595 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
596 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
598 linked_attributes[i].value.blob->data,
599 linked_attributes[i].value.blob->length);
606 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
607 struct libnet_Vampire *r)
609 struct libnet_JoinDomain *join;
610 struct provision_store_self_join_settings *set_secrets;
611 struct libnet_BecomeDC b;
612 struct libnet_vampire_cb_state *s;
613 struct ldb_message *msg;
614 const char *error_string;
619 const char *account_name;
620 const char *netbios_name;
622 r->out.error_string = NULL;
624 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
626 return NT_STATUS_NO_MEMORY;
629 if (r->in.netbios_name != NULL) {
630 netbios_name = r->in.netbios_name;
632 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
635 r->out.error_string = NULL;
636 return NT_STATUS_NO_MEMORY;
640 account_name = talloc_asprintf(join, "%s$", netbios_name);
643 r->out.error_string = NULL;
644 return NT_STATUS_NO_MEMORY;
647 /* Re-use the domain we are joining as the domain for the user
648 * to be authenticated with, unless they specified
650 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
652 join->in.domain_name = r->in.domain_name;
653 join->in.account_name = account_name;
654 join->in.netbios_name = netbios_name;
655 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
656 join->in.acct_type = ACB_WSTRUST;
657 join->in.recreate_account = false;
658 status = libnet_JoinDomain(ctx, join, join);
659 if (!NT_STATUS_IS_OK(status)) {
660 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
665 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
666 netbios_name, join->out.domain_name, join->out.realm,
669 return NT_STATUS_NO_MEMORY;
671 talloc_steal(s, join);
676 * We now know the domain and realm for sure - if they didn't
677 * put one on the command line, use this for the rest of the
679 cli_credentials_set_realm(ctx->cred, join->out.realm, CRED_GUESS_ENV);
680 cli_credentials_set_domain(ctx->cred, join->out.domain_name, CRED_GUESS_ENV);
682 /* Now set these values into the smb.conf - we probably had
683 * empty or useless defaults here from whatever smb.conf we
685 lp_set_cmdline(s->lp_ctx, "realm", join->out.realm);
686 lp_set_cmdline(s->lp_ctx, "workgroup", join->out.domain_name);
688 b.in.domain_dns_name = join->out.realm;
689 b.in.domain_netbios_name = join->out.domain_name;
690 b.in.domain_sid = join->out.domain_sid;
691 b.in.source_dsa_address = join->out.samr_binding->host;
692 b.in.dest_dsa_netbios_name = netbios_name;
694 b.in.callbacks.private_data = s;
695 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
696 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
697 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
698 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
699 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
701 b.in.rodc_join = lp_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
703 status = libnet_BecomeDC(ctx, s, &b);
704 if (!NT_STATUS_IS_OK(status)) {
705 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
710 msg = ldb_msg_new(s);
712 printf("ldb_msg_new() failed\n");
714 return NT_STATUS_NO_MEMORY;
716 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
718 printf("ldb_msg_new(@ROOTDSE) failed\n");
720 return NT_STATUS_NO_MEMORY;
723 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
724 if (ldb_ret != LDB_SUCCESS) {
725 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
727 return NT_STATUS_NO_MEMORY;
730 for (i=0; i < msg->num_elements; i++) {
731 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
734 printf("mark ROOTDSE with isSynchronized=TRUE\n");
735 ldb_ret = ldb_modify(s->ldb, msg);
736 if (ldb_ret != LDB_SUCCESS) {
737 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
739 return NT_STATUS_INTERNAL_DB_ERROR;
742 /* prepare the transaction - this prepares to commit all the changes in
743 the ldb from the whole vampire. Note that this
744 triggers the writing of the linked attribute backlinks.
746 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
747 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
748 return NT_STATUS_INTERNAL_DB_ERROR;
751 set_secrets = talloc(s, struct provision_store_self_join_settings);
753 r->out.error_string = NULL;
755 return NT_STATUS_NO_MEMORY;
758 ZERO_STRUCTP(set_secrets);
759 set_secrets->domain_name = join->out.domain_name;
760 set_secrets->realm = join->out.realm;
761 set_secrets->netbios_name = netbios_name;
762 set_secrets->secure_channel_type = SEC_CHAN_BDC;
763 set_secrets->machine_password = join->out.join_password;
764 set_secrets->key_version_number = join->out.kvno;
765 set_secrets->domain_sid = join->out.domain_sid;
767 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
768 if (!NT_STATUS_IS_OK(status)) {
769 r->out.error_string = talloc_steal(mem_ctx, error_string);
774 r->out.domain_name = talloc_steal(mem_ctx, join->out.domain_name);
775 r->out.domain_sid = dom_sid_dup(mem_ctx, join->out.domain_sid);
777 /* commit the transaction now we know the secrets were written
780 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
781 printf("Failed to commit vampire transaction\n");
782 return NT_STATUS_INTERNAL_DB_ERROR;