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 struct dsdb_schema *provision_schema;
64 const struct dsdb_schema *schema;
66 struct ldb_context *ldb;
69 uint32_t object_count;
70 struct drsuapi_DsReplicaObjectListItemEx *first_object;
71 struct drsuapi_DsReplicaObjectListItemEx *last_object;
74 const char *targetdir;
76 struct loadparm_context *lp_ctx;
77 struct tevent_context *event_ctx;
78 unsigned total_objects;
82 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
83 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
84 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
85 const char *netbios_name, const char *domain_name, const char *realm,
86 const char *targetdir)
88 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
94 s->event_ctx = event_ctx;
95 s->netbios_name = netbios_name;
96 s->domain_name = domain_name;
98 s->targetdir = targetdir;
102 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
104 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
108 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
110 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
111 return state->lp_ctx;
114 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
115 const struct libnet_BecomeDC_PrepareDB *p)
117 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
118 struct provision_settings settings;
119 struct provision_result result;
122 ZERO_STRUCT(settings);
123 settings.site_name = p->dest_dsa->site_name;
124 settings.root_dn_str = p->forest->root_dn_str;
125 settings.domain_dn_str = p->domain->dn_str;
126 settings.config_dn_str = p->forest->config_dn_str;
127 settings.schema_dn_str = p->forest->schema_dn_str;
128 settings.netbios_name = p->dest_dsa->netbios_name;
129 settings.realm = s->realm;
130 settings.domain = s->domain_name;
131 settings.server_dn_str = p->dest_dsa->server_dn_str;
132 settings.machine_password = generate_random_password(s, 16, 255);
133 settings.targetdir = s->targetdir;
135 status = provision_bare(s, s->lp_ctx, &settings, &result);
137 if (!NT_STATUS_IS_OK(status)) {
141 s->ldb = talloc_steal(s, result.samdb);
142 s->lp_ctx = talloc_steal(s, result.lp_ctx);
143 s->provision_schema = dsdb_get_schema(s->ldb, s);
145 /* wrap the entire vapire operation in a transaction. This
146 isn't just cosmetic - we use this to ensure that linked
147 attribute back links are added at the end by relying on a
148 transaction commit hook in the linked attributes module. We
149 need to do this as the order of objects coming from the
150 server is not sufficiently deterministic to know that the
151 record that a backlink needs to be created in has itself
152 been created before the object containing the forward link
153 has come over the wire */
154 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
155 return NT_STATUS_FOOBAR;
163 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
164 const struct libnet_BecomeDC_CheckOptions *o)
166 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
168 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
170 o->domain->netbios_name, o->domain->dns_name));
172 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
173 o->source_dsa->dns_name, o->source_dsa->site_name));
175 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
176 "\tschema object_version[%u]\n"
177 "\tdomain behavior_version[%u]\n"
178 "\tdomain w2k3_update_revision[%u]\n",
179 o->forest->crossref_behavior_version,
180 o->forest->schema_object_version,
181 o->domain->behavior_version,
182 o->domain->w2k3_update_revision));
187 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
188 const struct libnet_BecomeDC_StoreChunk *c)
191 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
192 uint32_t object_count;
193 struct drsuapi_DsReplicaObjectListItemEx *first_object;
194 uint32_t linked_attributes_count;
195 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
196 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
197 struct dsdb_extended_replicated_objects *schema_objs_1, *schema_objs_2;
198 struct repsFromTo1 *s_dsa;
200 struct ldb_message *msg;
201 struct ldb_val prefixMap_val;
202 struct ldb_message_element *prefixMap_el;
203 struct ldb_val schemaInfo_val;
209 DEBUG(0,("Analyze and apply schema objects\n"));
211 s_dsa = talloc_zero(s, struct repsFromTo1);
212 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
213 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
214 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
216 switch (c->ctr_level) {
218 mapping_ctr = &c->ctr1->mapping_ctr;
219 object_count = s->schema_part.object_count;
220 first_object = s->schema_part.first_object;
221 linked_attributes_count = 0;
222 linked_attributes = NULL;
223 s_dsa->highwatermark = c->ctr1->new_highwatermark;
224 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
225 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
226 uptodateness_vector = NULL; /* TODO: map it */
229 mapping_ctr = &c->ctr6->mapping_ctr;
230 object_count = s->schema_part.object_count;
231 first_object = s->schema_part.first_object;
232 linked_attributes_count = c->ctr6->linked_attributes_count;
233 linked_attributes = c->ctr6->linked_attributes;
234 s_dsa->highwatermark = c->ctr6->new_highwatermark;
235 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
236 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
237 uptodateness_vector = c->ctr6->uptodateness_vector;
240 return NT_STATUS_INVALID_PARAMETER;
243 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
244 | DRSUAPI_DRS_INIT_SYNC
245 | DRSUAPI_DRS_PER_SYNC;
246 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
248 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
249 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
250 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
251 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
252 s_dsa->other_info->dns_name = tmp_dns_name;
254 s->provision_schema->relax_OID_conversions = true;
256 /* Now convert the schema elements again, using the schema we just imported */
257 status = dsdb_extended_replicated_objects_convert(s->ldb,
262 linked_attributes_count,
268 if (!W_ERROR_IS_OK(status)) {
269 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
270 return werror_to_ntstatus(status);
273 for (i=0; i < schema_objs_1->num_objects; i++) {
274 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_made_schema, schema_objs_1->objects[i].msg);
275 if (!W_ERROR_IS_OK(status)) {
276 DEBUG(0,("Failed to convert object %s into a schema element: %s\n",
277 ldb_dn_get_linearized(schema_objs_1->objects[i].msg->dn),
278 win_errstr(status)));
279 return werror_to_ntstatus(status);
282 /* We don't need the first conversion of the schema any more */
283 talloc_free(schema_objs_1);
285 /* attach the schema we just brought over DRS to the ldb */
286 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
287 if (ret != LDB_SUCCESS) {
288 DEBUG(0,("Failed to attach schema from DRS.\n"));
289 return NT_STATUS_FOOBAR;
292 /* we don't want to access the self made schema anymore */
293 s->schema = s->self_made_schema;
294 s->self_made_schema = NULL;
296 /* Now convert the schema elements again, using the schema we just imported - we do this
297 'just in case' the schema in our LDIF was wrong, but correct enough to read a valid schema */
298 status = dsdb_extended_replicated_objects_convert(s->ldb,
303 linked_attributes_count,
309 if (!W_ERROR_IS_OK(status)) {
310 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
311 return werror_to_ntstatus(status);
314 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
315 for (i=0; i < schema_objs_2->num_objects; i++) {
316 struct ldb_ldif ldif;
317 fprintf(stdout, "#\n");
318 ldif.changetype = LDB_CHANGETYPE_NONE;
319 ldif.msg = schema_objs_2->objects[i].msg;
320 ldb_ldif_write_file(s->ldb, stdout, &ldif);
321 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs_2->objects[i].meta_data);
325 status = dsdb_extended_replicated_objects_commit(s->ldb, schema_objs_2, &seq_num);
326 if (!W_ERROR_IS_OK(status)) {
327 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
328 return werror_to_ntstatus(status);
331 msg = ldb_msg_new(schema_objs_2);
332 NT_STATUS_HAVE_NO_MEMORY(msg);
333 msg->dn = schema_objs_2->partition_dn;
335 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
336 if (!W_ERROR_IS_OK(status)) {
337 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
338 return werror_to_ntstatus(status);
341 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
342 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
343 if (ret != LDB_SUCCESS) {
344 return NT_STATUS_FOOBAR;
346 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
348 ret = ldb_modify(s->ldb, msg);
349 if (ret != LDB_SUCCESS) {
350 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_strerror(ret)));
351 return NT_STATUS_FOOBAR;
355 talloc_free(schema_objs_2);
357 /* We must set these up to ensure the replMetaData is written
358 * correctly, before our NTDS Settings entry is replicated */
359 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
361 DEBUG(0,("Failed to set cached ntds invocationId\n"));
362 return NT_STATUS_FOOBAR;
364 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
366 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
367 return NT_STATUS_FOOBAR;
370 s->schema = dsdb_get_schema(s->ldb, s);
372 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
373 return NT_STATUS_FOOBAR;
379 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
380 const struct libnet_BecomeDC_StoreChunk *c)
382 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
384 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
385 uint32_t nc_object_count;
386 uint32_t object_count;
387 struct drsuapi_DsReplicaObjectListItemEx *first_object;
388 struct drsuapi_DsReplicaObjectListItemEx *cur;
389 uint32_t nc_linked_attributes_count;
390 uint32_t linked_attributes_count;
391 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
393 switch (c->ctr_level) {
395 mapping_ctr = &c->ctr1->mapping_ctr;
396 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
397 object_count = c->ctr1->object_count;
398 first_object = c->ctr1->first_object;
399 nc_linked_attributes_count = 0;
400 linked_attributes_count = 0;
401 linked_attributes = NULL;
404 mapping_ctr = &c->ctr6->mapping_ctr;
405 nc_object_count = c->ctr6->nc_object_count;
406 object_count = c->ctr6->object_count;
407 first_object = c->ctr6->first_object;
408 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
409 linked_attributes_count = c->ctr6->linked_attributes_count;
410 linked_attributes = c->ctr6->linked_attributes;
413 return NT_STATUS_INVALID_PARAMETER;
416 if (nc_object_count) {
417 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
418 c->partition->nc.dn, object_count, nc_object_count,
419 linked_attributes_count, nc_linked_attributes_count));
421 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
422 c->partition->nc.dn, object_count, linked_attributes_count));
426 s->self_made_schema = dsdb_new_schema(s);
428 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
430 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
431 if (!W_ERROR_IS_OK(status)) {
432 return werror_to_ntstatus(status);
435 s->schema = s->self_made_schema;
437 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->schema->prefixmap, mapping_ctr);
438 if (!W_ERROR_IS_OK(status)) {
439 return werror_to_ntstatus(status);
443 if (!s->schema_part.first_object) {
444 s->schema_part.object_count = object_count;
445 s->schema_part.first_object = talloc_steal(s, first_object);
447 s->schema_part.object_count += object_count;
448 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
451 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
452 s->schema_part.last_object = cur;
454 if (!c->partition->more_data) {
455 return libnet_vampire_cb_apply_schema(s, c);
461 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
462 const struct libnet_BecomeDC_StoreChunk *c)
464 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
466 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
467 uint32_t nc_object_count;
468 uint32_t object_count;
469 struct drsuapi_DsReplicaObjectListItemEx *first_object;
470 uint32_t nc_linked_attributes_count;
471 uint32_t linked_attributes_count;
472 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
473 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
474 struct dsdb_extended_replicated_objects *objs;
475 struct repsFromTo1 *s_dsa;
480 s_dsa = talloc_zero(s, struct repsFromTo1);
481 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
482 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
483 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
485 switch (c->ctr_level) {
487 mapping_ctr = &c->ctr1->mapping_ctr;
488 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
489 object_count = c->ctr1->object_count;
490 first_object = c->ctr1->first_object;
491 nc_linked_attributes_count = 0;
492 linked_attributes_count = 0;
493 linked_attributes = NULL;
494 s_dsa->highwatermark = c->ctr1->new_highwatermark;
495 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
496 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
497 uptodateness_vector = NULL; /* TODO: map it */
500 mapping_ctr = &c->ctr6->mapping_ctr;
501 nc_object_count = c->ctr6->nc_object_count;
502 object_count = c->ctr6->object_count;
503 first_object = c->ctr6->first_object;
504 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
505 linked_attributes_count = c->ctr6->linked_attributes_count;
506 linked_attributes = c->ctr6->linked_attributes;
507 s_dsa->highwatermark = c->ctr6->new_highwatermark;
508 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
509 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
510 uptodateness_vector = c->ctr6->uptodateness_vector;
513 return NT_STATUS_INVALID_PARAMETER;
516 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
517 | DRSUAPI_DRS_INIT_SYNC
518 | DRSUAPI_DRS_PER_SYNC;
519 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
521 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
522 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
523 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
524 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
525 s_dsa->other_info->dns_name = tmp_dns_name;
527 /* we want to show a count per partition */
528 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
529 s->total_objects = 0;
530 talloc_free(s->last_partition);
531 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
533 s->total_objects += object_count;
535 if (nc_object_count) {
536 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
537 c->partition->nc.dn, s->total_objects, nc_object_count,
538 linked_attributes_count, nc_linked_attributes_count));
540 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
541 c->partition->nc.dn, s->total_objects, linked_attributes_count));
545 status = dsdb_extended_replicated_objects_convert(s->ldb,
550 linked_attributes_count,
556 if (!W_ERROR_IS_OK(status)) {
557 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
558 return werror_to_ntstatus(status);
561 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
562 for (i=0; i < objs->num_objects; i++) {
563 struct ldb_ldif ldif;
564 fprintf(stdout, "#\n");
565 ldif.changetype = LDB_CHANGETYPE_NONE;
566 ldif.msg = objs->objects[i].msg;
567 ldb_ldif_write_file(s->ldb, stdout, &ldif);
568 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
571 status = dsdb_extended_replicated_objects_commit(s->ldb,
573 if (!W_ERROR_IS_OK(status)) {
574 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
575 return werror_to_ntstatus(status);
581 for (i=0; i < linked_attributes_count; i++) {
582 const struct dsdb_attribute *sa;
584 if (!linked_attributes[i].identifier) {
585 return NT_STATUS_FOOBAR;
588 if (!linked_attributes[i].value.blob) {
589 return NT_STATUS_FOOBAR;
592 sa = dsdb_attribute_by_attributeID_id(s->schema,
593 linked_attributes[i].attid);
595 return NT_STATUS_FOOBAR;
598 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
599 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
600 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
602 linked_attributes[i].value.blob->data,
603 linked_attributes[i].value.blob->length);
610 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
611 struct libnet_Vampire *r)
613 struct libnet_JoinDomain *join;
614 struct provision_store_self_join_settings *set_secrets;
615 struct libnet_BecomeDC b;
616 struct libnet_vampire_cb_state *s;
617 struct ldb_message *msg;
618 const char *error_string;
623 const char *account_name;
624 const char *netbios_name;
626 r->out.error_string = NULL;
628 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
630 return NT_STATUS_NO_MEMORY;
633 if (r->in.netbios_name != NULL) {
634 netbios_name = r->in.netbios_name;
636 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
639 r->out.error_string = NULL;
640 return NT_STATUS_NO_MEMORY;
644 account_name = talloc_asprintf(join, "%s$", netbios_name);
647 r->out.error_string = NULL;
648 return NT_STATUS_NO_MEMORY;
651 /* Re-use the domain we are joining as the domain for the user
652 * to be authenticated with, unless they specified
654 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
656 join->in.domain_name = r->in.domain_name;
657 join->in.account_name = account_name;
658 join->in.netbios_name = netbios_name;
659 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
660 join->in.acct_type = ACB_WSTRUST;
661 join->in.recreate_account = false;
662 status = libnet_JoinDomain(ctx, join, join);
663 if (!NT_STATUS_IS_OK(status)) {
664 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
669 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
670 netbios_name, join->out.domain_name, join->out.realm,
673 return NT_STATUS_NO_MEMORY;
675 talloc_steal(s, join);
680 * We now know the domain and realm for sure - if they didn't
681 * put one on the command line, use this for the rest of the
683 cli_credentials_set_realm(ctx->cred, join->out.realm, CRED_GUESS_ENV);
684 cli_credentials_set_domain(ctx->cred, join->out.domain_name, CRED_GUESS_ENV);
686 /* Now set these values into the smb.conf - we probably had
687 * empty or useless defaults here from whatever smb.conf we
689 lp_set_cmdline(s->lp_ctx, "realm", join->out.realm);
690 lp_set_cmdline(s->lp_ctx, "workgroup", join->out.domain_name);
692 b.in.domain_dns_name = join->out.realm;
693 b.in.domain_netbios_name = join->out.domain_name;
694 b.in.domain_sid = join->out.domain_sid;
695 b.in.source_dsa_address = join->out.samr_binding->host;
696 b.in.dest_dsa_netbios_name = netbios_name;
698 b.in.callbacks.private_data = s;
699 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
700 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
701 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
702 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
703 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
705 b.in.rodc_join = lp_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
707 status = libnet_BecomeDC(ctx, s, &b);
708 if (!NT_STATUS_IS_OK(status)) {
709 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
714 msg = ldb_msg_new(s);
716 printf("ldb_msg_new() failed\n");
718 return NT_STATUS_NO_MEMORY;
720 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
722 printf("ldb_msg_new(@ROOTDSE) failed\n");
724 return NT_STATUS_NO_MEMORY;
727 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
728 if (ldb_ret != LDB_SUCCESS) {
729 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
731 return NT_STATUS_NO_MEMORY;
734 for (i=0; i < msg->num_elements; i++) {
735 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
738 printf("mark ROOTDSE with isSynchronized=TRUE\n");
739 ldb_ret = ldb_modify(s->ldb, msg);
740 if (ldb_ret != LDB_SUCCESS) {
741 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
743 return NT_STATUS_INTERNAL_DB_ERROR;
746 /* prepare the transaction - this prepares to commit all the changes in
747 the ldb from the whole vampire. Note that this
748 triggers the writing of the linked attribute backlinks.
750 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
751 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
752 return NT_STATUS_INTERNAL_DB_ERROR;
755 set_secrets = talloc(s, struct provision_store_self_join_settings);
757 r->out.error_string = NULL;
759 return NT_STATUS_NO_MEMORY;
762 ZERO_STRUCTP(set_secrets);
763 set_secrets->domain_name = join->out.domain_name;
764 set_secrets->realm = join->out.realm;
765 set_secrets->netbios_name = netbios_name;
766 set_secrets->secure_channel_type = SEC_CHAN_BDC;
767 set_secrets->machine_password = join->out.join_password;
768 set_secrets->key_version_number = join->out.kvno;
769 set_secrets->domain_sid = join->out.domain_sid;
771 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
772 if (!NT_STATUS_IS_OK(status)) {
773 r->out.error_string = talloc_steal(mem_ctx, error_string);
778 r->out.domain_name = talloc_steal(mem_ctx, join->out.domain_name);
779 r->out.domain_sid = dom_sid_dup(mem_ctx, join->out.domain_sid);
781 /* commit the transaction now we know the secrets were written
784 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
785 printf("Failed to commit vampire transaction\n");
786 return NT_STATUS_INTERNAL_DB_ERROR;