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 = result.samdb;
141 s->lp_ctx = 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 struct drsuapi_DsReplicaObjectListItemEx *cur;
193 uint32_t linked_attributes_count;
194 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
195 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
196 struct dsdb_extended_replicated_objects *objs;
197 struct repsFromTo1 *s_dsa;
199 struct ldb_message *msg;
200 struct ldb_val prefixMap_val;
201 struct ldb_message_element *prefixMap_el;
202 struct ldb_val schemaInfo_val;
208 DEBUG(0,("Analyze and apply schema objects\n"));
210 s_dsa = talloc_zero(s, struct repsFromTo1);
211 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
212 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
213 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
215 switch (c->ctr_level) {
217 mapping_ctr = &c->ctr1->mapping_ctr;
218 object_count = s->schema_part.object_count;
219 first_object = s->schema_part.first_object;
220 linked_attributes_count = 0;
221 linked_attributes = NULL;
222 s_dsa->highwatermark = c->ctr1->new_highwatermark;
223 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
224 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
225 uptodateness_vector = NULL; /* TODO: map it */
228 mapping_ctr = &c->ctr6->mapping_ctr;
229 object_count = s->schema_part.object_count;
230 first_object = s->schema_part.first_object;
231 linked_attributes_count = c->ctr6->linked_attributes_count;
232 linked_attributes = c->ctr6->linked_attributes;
233 s_dsa->highwatermark = c->ctr6->new_highwatermark;
234 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
235 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
236 uptodateness_vector = c->ctr6->uptodateness_vector;
239 return NT_STATUS_INVALID_PARAMETER;
242 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
243 | DRSUAPI_DRS_INIT_SYNC
244 | DRSUAPI_DRS_PER_SYNC;
245 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
247 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
248 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
249 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
250 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
251 s_dsa->other_info->dns_name = tmp_dns_name;
253 for (cur = first_object; cur; cur = cur->next_object) {
254 bool is_attr = false;
255 bool is_class = false;
257 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
258 struct drsuapi_DsReplicaAttribute *a;
260 const char *oid = NULL;
262 a = &cur->object.attribute_ctr.attributes[i];
263 status = dsdb_schema_pfm_oid_from_attid(s->self_made_schema->prefixmap,
265 if (!W_ERROR_IS_OK(status)) {
266 return werror_to_ntstatus(status);
270 case DRSUAPI_ATTRIBUTE_objectClass:
271 for (j=0; j < a->value_ctr.num_values; j++) {
272 uint32_t val = 0xFFFFFFFF;
274 if (a->value_ctr.values[j].blob
275 && a->value_ctr.values[j].blob->length == 4) {
276 val = IVAL(a->value_ctr.values[j].blob->data,0);
279 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
282 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
294 struct dsdb_attribute *sa;
296 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
297 NT_STATUS_HAVE_NO_MEMORY(sa);
299 status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
300 if (!W_ERROR_IS_OK(status)) {
301 return werror_to_ntstatus(status);
304 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
308 struct dsdb_class *sc;
310 sc = talloc_zero(s->self_made_schema, struct dsdb_class);
311 NT_STATUS_HAVE_NO_MEMORY(sc);
313 status = dsdb_class_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sc);
314 if (!W_ERROR_IS_OK(status)) {
315 return werror_to_ntstatus(status);
317 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
321 /* attach the schema to the ldb */
322 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
323 if (ret != LDB_SUCCESS) {
324 DEBUG(0,("Failed to attach schema from DRS.\n"));
325 return NT_STATUS_FOOBAR;
327 /* we don't want to access the self made schema anymore */
328 s->schema = s->self_made_schema;
329 s->self_made_schema = NULL;
331 /* Now convert the schema elements again, using the schema we just imported */
332 status = dsdb_extended_replicated_objects_convert(s->ldb,
337 linked_attributes_count,
343 if (!W_ERROR_IS_OK(status)) {
344 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
345 return werror_to_ntstatus(status);
348 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
349 for (i=0; i < objs->num_objects; i++) {
350 struct ldb_ldif ldif;
351 fprintf(stdout, "#\n");
352 ldif.changetype = LDB_CHANGETYPE_NONE;
353 ldif.msg = objs->objects[i].msg;
354 ldb_ldif_write_file(s->ldb, stdout, &ldif);
355 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
359 status = dsdb_extended_replicated_objects_commit(s->ldb, objs, &seq_num);
360 if (!W_ERROR_IS_OK(status)) {
361 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
362 return werror_to_ntstatus(status);
365 msg = ldb_msg_new(objs);
366 NT_STATUS_HAVE_NO_MEMORY(msg);
367 msg->dn = objs->partition_dn;
369 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
370 if (!W_ERROR_IS_OK(status)) {
371 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
372 return werror_to_ntstatus(status);
375 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
376 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
377 if (ret != LDB_SUCCESS) {
378 return NT_STATUS_FOOBAR;
380 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
382 ret = ldb_modify(s->ldb, msg);
383 if (ret != LDB_SUCCESS) {
384 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
385 return NT_STATUS_FOOBAR;
391 /* We must set these up to ensure the replMetaData is written
392 * correctly, before our NTDS Settings entry is replicated */
393 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
395 DEBUG(0,("Failed to set cached ntds invocationId\n"));
396 return NT_STATUS_FOOBAR;
398 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
400 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
401 return NT_STATUS_FOOBAR;
404 s->schema = dsdb_get_schema(s->ldb, s);
406 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
407 return NT_STATUS_FOOBAR;
413 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
414 const struct libnet_BecomeDC_StoreChunk *c)
416 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
418 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
419 uint32_t nc_object_count;
420 uint32_t object_count;
421 struct drsuapi_DsReplicaObjectListItemEx *first_object;
422 struct drsuapi_DsReplicaObjectListItemEx *cur;
423 uint32_t nc_linked_attributes_count;
424 uint32_t linked_attributes_count;
425 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
427 switch (c->ctr_level) {
429 mapping_ctr = &c->ctr1->mapping_ctr;
430 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
431 object_count = c->ctr1->object_count;
432 first_object = c->ctr1->first_object;
433 nc_linked_attributes_count = 0;
434 linked_attributes_count = 0;
435 linked_attributes = NULL;
438 mapping_ctr = &c->ctr6->mapping_ctr;
439 nc_object_count = c->ctr6->nc_object_count;
440 object_count = c->ctr6->object_count;
441 first_object = c->ctr6->first_object;
442 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
443 linked_attributes_count = c->ctr6->linked_attributes_count;
444 linked_attributes = c->ctr6->linked_attributes;
447 return NT_STATUS_INVALID_PARAMETER;
450 if (nc_object_count) {
451 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
452 c->partition->nc.dn, object_count, nc_object_count,
453 linked_attributes_count, nc_linked_attributes_count));
455 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
456 c->partition->nc.dn, object_count, linked_attributes_count));
460 s->self_made_schema = dsdb_new_schema(s);
462 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
464 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
465 if (!W_ERROR_IS_OK(status)) {
466 return werror_to_ntstatus(status);
469 s->schema = s->self_made_schema;
471 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->schema->prefixmap, mapping_ctr);
472 if (!W_ERROR_IS_OK(status)) {
473 return werror_to_ntstatus(status);
477 if (!s->schema_part.first_object) {
478 s->schema_part.object_count = object_count;
479 s->schema_part.first_object = talloc_steal(s, first_object);
481 s->schema_part.object_count += object_count;
482 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
485 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
486 s->schema_part.last_object = cur;
488 if (!c->partition->more_data) {
489 return libnet_vampire_cb_apply_schema(s, c);
495 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
496 const struct libnet_BecomeDC_StoreChunk *c)
498 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
500 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
501 uint32_t nc_object_count;
502 uint32_t object_count;
503 struct drsuapi_DsReplicaObjectListItemEx *first_object;
504 uint32_t nc_linked_attributes_count;
505 uint32_t linked_attributes_count;
506 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
507 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
508 struct dsdb_extended_replicated_objects *objs;
509 struct repsFromTo1 *s_dsa;
514 s_dsa = talloc_zero(s, struct repsFromTo1);
515 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
516 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
517 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
519 switch (c->ctr_level) {
521 mapping_ctr = &c->ctr1->mapping_ctr;
522 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
523 object_count = c->ctr1->object_count;
524 first_object = c->ctr1->first_object;
525 nc_linked_attributes_count = 0;
526 linked_attributes_count = 0;
527 linked_attributes = NULL;
528 s_dsa->highwatermark = c->ctr1->new_highwatermark;
529 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
530 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
531 uptodateness_vector = NULL; /* TODO: map it */
534 mapping_ctr = &c->ctr6->mapping_ctr;
535 nc_object_count = c->ctr6->nc_object_count;
536 object_count = c->ctr6->object_count;
537 first_object = c->ctr6->first_object;
538 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
539 linked_attributes_count = c->ctr6->linked_attributes_count;
540 linked_attributes = c->ctr6->linked_attributes;
541 s_dsa->highwatermark = c->ctr6->new_highwatermark;
542 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
543 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
544 uptodateness_vector = c->ctr6->uptodateness_vector;
547 return NT_STATUS_INVALID_PARAMETER;
550 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
551 | DRSUAPI_DRS_INIT_SYNC
552 | DRSUAPI_DRS_PER_SYNC;
553 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
555 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
556 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
557 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
558 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
559 s_dsa->other_info->dns_name = tmp_dns_name;
561 /* we want to show a count per partition */
562 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
563 s->total_objects = 0;
564 talloc_free(s->last_partition);
565 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
567 s->total_objects += object_count;
569 if (nc_object_count) {
570 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
571 c->partition->nc.dn, s->total_objects, nc_object_count,
572 linked_attributes_count, nc_linked_attributes_count));
574 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
575 c->partition->nc.dn, s->total_objects, linked_attributes_count));
579 status = dsdb_extended_replicated_objects_convert(s->ldb,
584 linked_attributes_count,
590 if (!W_ERROR_IS_OK(status)) {
591 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
592 return werror_to_ntstatus(status);
595 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
596 for (i=0; i < objs->num_objects; i++) {
597 struct ldb_ldif ldif;
598 fprintf(stdout, "#\n");
599 ldif.changetype = LDB_CHANGETYPE_NONE;
600 ldif.msg = objs->objects[i].msg;
601 ldb_ldif_write_file(s->ldb, stdout, &ldif);
602 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
605 status = dsdb_extended_replicated_objects_commit(s->ldb,
607 if (!W_ERROR_IS_OK(status)) {
608 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
609 return werror_to_ntstatus(status);
615 for (i=0; i < linked_attributes_count; i++) {
616 const struct dsdb_attribute *sa;
618 if (!linked_attributes[i].identifier) {
619 return NT_STATUS_FOOBAR;
622 if (!linked_attributes[i].value.blob) {
623 return NT_STATUS_FOOBAR;
626 sa = dsdb_attribute_by_attributeID_id(s->schema,
627 linked_attributes[i].attid);
629 return NT_STATUS_FOOBAR;
632 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
633 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
634 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
636 linked_attributes[i].value.blob->data,
637 linked_attributes[i].value.blob->length);
644 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
645 struct libnet_Vampire *r)
647 struct libnet_JoinDomain *join;
648 struct provision_store_self_join_settings *set_secrets;
649 struct libnet_BecomeDC b;
650 struct libnet_vampire_cb_state *s;
651 struct ldb_message *msg;
652 const char *error_string;
657 const char *account_name;
658 const char *netbios_name;
660 r->out.error_string = NULL;
662 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
664 return NT_STATUS_NO_MEMORY;
667 if (r->in.netbios_name != NULL) {
668 netbios_name = r->in.netbios_name;
670 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
673 r->out.error_string = NULL;
674 return NT_STATUS_NO_MEMORY;
678 account_name = talloc_asprintf(join, "%s$", netbios_name);
681 r->out.error_string = NULL;
682 return NT_STATUS_NO_MEMORY;
685 /* Re-use the domain we are joining as the domain for the user
686 * to be authenticated with, unless they specified
688 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
690 join->in.domain_name = r->in.domain_name;
691 join->in.account_name = account_name;
692 join->in.netbios_name = netbios_name;
693 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
694 join->in.acct_type = ACB_WSTRUST;
695 join->in.recreate_account = false;
696 status = libnet_JoinDomain(ctx, join, join);
697 if (!NT_STATUS_IS_OK(status)) {
698 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
703 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
704 netbios_name, join->out.domain_name, join->out.realm,
707 return NT_STATUS_NO_MEMORY;
709 talloc_steal(s, join);
714 * We now know the domain and realm for sure - if they didn't
715 * put one on the command line, use this for the rest of the
717 cli_credentials_set_realm(ctx->cred, join->out.realm, CRED_GUESS_ENV);
718 cli_credentials_set_domain(ctx->cred, join->out.domain_name, CRED_GUESS_ENV);
720 /* Now set these values into the smb.conf - we probably had
721 * empty or useless defaults here from whatever smb.conf we
723 lp_set_cmdline(s->lp_ctx, "realm", join->out.realm);
724 lp_set_cmdline(s->lp_ctx, "workgroup", join->out.domain_name);
726 b.in.domain_dns_name = join->out.realm;
727 b.in.domain_netbios_name = join->out.domain_name;
728 b.in.domain_sid = join->out.domain_sid;
729 b.in.source_dsa_address = join->out.samr_binding->host;
730 b.in.dest_dsa_netbios_name = netbios_name;
732 b.in.callbacks.private_data = s;
733 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
734 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
735 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
736 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
737 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
739 b.in.rodc_join = lp_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
741 status = libnet_BecomeDC(ctx, s, &b);
742 if (!NT_STATUS_IS_OK(status)) {
743 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
748 msg = ldb_msg_new(s);
750 printf("ldb_msg_new() failed\n");
752 return NT_STATUS_NO_MEMORY;
754 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
756 printf("ldb_msg_new(@ROOTDSE) failed\n");
758 return NT_STATUS_NO_MEMORY;
761 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
762 if (ldb_ret != LDB_SUCCESS) {
763 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
765 return NT_STATUS_NO_MEMORY;
768 for (i=0; i < msg->num_elements; i++) {
769 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
772 printf("mark ROOTDSE with isSynchronized=TRUE\n");
773 ldb_ret = ldb_modify(s->ldb, msg);
774 if (ldb_ret != LDB_SUCCESS) {
775 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
777 return NT_STATUS_INTERNAL_DB_ERROR;
780 /* prepare the transaction - this prepares to commit all the changes in
781 the ldb from the whole vampire. Note that this
782 triggers the writing of the linked attribute backlinks.
784 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
785 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
786 return NT_STATUS_INTERNAL_DB_ERROR;
789 set_secrets = talloc(s, struct provision_store_self_join_settings);
791 r->out.error_string = NULL;
793 return NT_STATUS_NO_MEMORY;
796 ZERO_STRUCTP(set_secrets);
797 set_secrets->domain_name = join->out.domain_name;
798 set_secrets->realm = join->out.realm;
799 set_secrets->netbios_name = netbios_name;
800 set_secrets->secure_channel_type = SEC_CHAN_BDC;
801 set_secrets->machine_password = join->out.join_password;
802 set_secrets->key_version_number = join->out.kvno;
803 set_secrets->domain_sid = join->out.domain_sid;
805 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
806 if (!NT_STATUS_IS_OK(status)) {
807 r->out.error_string = talloc_steal(mem_ctx, error_string);
812 r->out.domain_name = talloc_steal(mem_ctx, join->out.domain_name);
813 r->out.domain_sid = dom_sid_dup(mem_ctx, join->out.domain_sid);
815 /* commit the transaction now we know the secrets were written
818 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
819 printf("Failed to commit vampire transaction\n");
820 return NT_STATUS_INTERNAL_DB_ERROR;