s4-repl: don't do double replication
[Samba/aatanasov.git] / source4 / libnet / libnet_vampire.c
blob327a64daea3bf0932a7728b82fced206dcc88f74
1 /*
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/>.
25 #include "includes.h"
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"
42 /*
43 List of tasks vampire.py must perform:
44 - Domain Join
45 - but don't write the secrets.ldb
46 - results for this should be enough to handle the provision
47 - if vampire method is samsync
48 - Provision using these results
49 - do we still want to support this NT4 technology?
50 - Start samsync with libnet code
51 - provision in the callback
52 - Write out the secrets database, using the code from libnet_Join
55 struct vampire_state {
56 const char *netbios_name;
57 struct libnet_JoinDomain *join;
58 struct cli_credentials *machine_account;
59 struct dsdb_schema *self_made_schema;
60 const struct dsdb_schema *schema;
62 struct ldb_context *ldb;
64 struct {
65 uint32_t object_count;
66 struct drsuapi_DsReplicaObjectListItemEx *first_object;
67 struct drsuapi_DsReplicaObjectListItemEx *last_object;
68 } schema_part;
70 const char *targetdir;
72 struct loadparm_context *lp_ctx;
73 struct tevent_context *event_ctx;
74 unsigned total_objects;
75 char *last_partition;
78 static NTSTATUS vampire_prepare_db(void *private_data,
79 const struct libnet_BecomeDC_PrepareDB *p)
81 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
82 struct provision_settings settings;
83 struct provision_result result;
84 NTSTATUS status;
86 ZERO_STRUCT(settings);
87 settings.site_name = p->dest_dsa->site_name;
88 settings.root_dn_str = p->forest->root_dn_str;
89 settings.domain_dn_str = p->domain->dn_str;
90 settings.config_dn_str = p->forest->config_dn_str;
91 settings.schema_dn_str = p->forest->schema_dn_str;
92 settings.netbios_name = p->dest_dsa->netbios_name;
93 settings.realm = s->join->out.realm;
94 settings.domain = s->join->out.domain_name;
95 settings.server_dn_str = p->dest_dsa->server_dn_str;
96 settings.machine_password = generate_random_str(s, 16);
97 settings.targetdir = s->targetdir;
99 status = provision_bare(s, s->lp_ctx, &settings, &result);
101 if (!NT_STATUS_IS_OK(status)) {
102 return status;
105 s->ldb = result.samdb;
106 s->lp_ctx = result.lp_ctx;
108 /* wrap the entire vapire operation in a transaction. This
109 isn't just cosmetic - we use this to ensure that linked
110 attribute back links are added at the end by relying on a
111 transaction commit hook in the linked attributes module. We
112 need to do this as the order of objects coming from the
113 server is not sufficiently deterministic to know that the
114 record that a backlink needs to be created in has itself
115 been created before the object containing the forward link
116 has come over the wire */
117 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
118 return NT_STATUS_FOOBAR;
121 return NT_STATUS_OK;
126 static NTSTATUS vampire_check_options(void *private_data,
127 const struct libnet_BecomeDC_CheckOptions *o)
129 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
131 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
132 s->netbios_name,
133 o->domain->netbios_name, o->domain->dns_name));
135 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
136 o->source_dsa->dns_name, o->source_dsa->site_name));
138 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
139 "\tschema object_version[%u]\n"
140 "\tdomain behavior_version[%u]\n"
141 "\tdomain w2k3_update_revision[%u]\n",
142 o->forest->crossref_behavior_version,
143 o->forest->schema_object_version,
144 o->domain->behavior_version,
145 o->domain->w2k3_update_revision));
147 return NT_STATUS_OK;
150 static NTSTATUS vampire_apply_schema(struct vampire_state *s,
151 const struct libnet_BecomeDC_StoreChunk *c)
153 WERROR status;
154 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
155 uint32_t object_count;
156 struct drsuapi_DsReplicaObjectListItemEx *first_object;
157 struct drsuapi_DsReplicaObjectListItemEx *cur;
158 uint32_t linked_attributes_count;
159 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
160 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
161 struct dsdb_extended_replicated_objects *objs;
162 struct repsFromTo1 *s_dsa;
163 char *tmp_dns_name;
164 struct ldb_message *msg;
165 struct ldb_val prefixMap_val;
166 struct ldb_message_element *prefixMap_el;
167 struct ldb_val schemaInfo_val;
168 uint32_t i;
169 int ret;
170 bool ok;
171 uint64_t seq_num;
173 DEBUG(0,("Analyze and apply schema objects\n"));
175 s_dsa = talloc_zero(s, struct repsFromTo1);
176 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
177 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
178 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
180 switch (c->ctr_level) {
181 case 1:
182 mapping_ctr = &c->ctr1->mapping_ctr;
183 object_count = s->schema_part.object_count;
184 first_object = s->schema_part.first_object;
185 linked_attributes_count = 0;
186 linked_attributes = NULL;
187 s_dsa->highwatermark = c->ctr1->new_highwatermark;
188 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
189 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
190 uptodateness_vector = NULL; /* TODO: map it */
191 break;
192 case 6:
193 mapping_ctr = &c->ctr6->mapping_ctr;
194 object_count = s->schema_part.object_count;
195 first_object = s->schema_part.first_object;
196 linked_attributes_count = c->ctr6->linked_attributes_count;
197 linked_attributes = c->ctr6->linked_attributes;
198 s_dsa->highwatermark = c->ctr6->new_highwatermark;
199 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
200 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
201 uptodateness_vector = c->ctr6->uptodateness_vector;
202 break;
203 default:
204 return NT_STATUS_INVALID_PARAMETER;
207 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
208 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
209 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
210 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
212 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
213 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
214 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
215 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
216 s_dsa->other_info->dns_name = tmp_dns_name;
218 for (cur = first_object; cur; cur = cur->next_object) {
219 bool is_attr = false;
220 bool is_class = false;
222 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
223 struct drsuapi_DsReplicaAttribute *a;
224 uint32_t j;
225 const char *oid = NULL;
227 a = &cur->object.attribute_ctr.attributes[i];
228 status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
229 if (!W_ERROR_IS_OK(status)) {
230 return werror_to_ntstatus(status);
233 switch (a->attid) {
234 case DRSUAPI_ATTRIBUTE_objectClass:
235 for (j=0; j < a->value_ctr.num_values; j++) {
236 uint32_t val = 0xFFFFFFFF;
238 if (a->value_ctr.values[j].blob
239 && a->value_ctr.values[j].blob->length == 4) {
240 val = IVAL(a->value_ctr.values[j].blob->data,0);
243 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
244 is_attr = true;
246 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
247 is_class = true;
251 break;
252 default:
253 break;
257 if (is_attr) {
258 struct dsdb_attribute *sa;
260 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
261 NT_STATUS_HAVE_NO_MEMORY(sa);
263 status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
264 if (!W_ERROR_IS_OK(status)) {
265 return werror_to_ntstatus(status);
268 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
271 if (is_class) {
272 struct dsdb_class *sc;
274 sc = talloc_zero(s->self_made_schema, struct dsdb_class);
275 NT_STATUS_HAVE_NO_MEMORY(sc);
277 status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
278 if (!W_ERROR_IS_OK(status)) {
279 return werror_to_ntstatus(status);
282 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
286 /* attach the schema to the ldb */
287 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
288 if (ret != LDB_SUCCESS) {
289 return NT_STATUS_FOOBAR;
291 /* we don't want to access the self made schema anymore */
292 s->self_made_schema = NULL;
293 s->schema = dsdb_get_schema(s->ldb);
295 status = dsdb_extended_replicated_objects_commit(s->ldb,
296 c->partition->nc.dn,
297 mapping_ctr,
298 object_count,
299 first_object,
300 linked_attributes_count,
301 linked_attributes,
302 s_dsa,
303 uptodateness_vector,
304 c->gensec_skey,
305 s, &objs, &seq_num);
306 if (!W_ERROR_IS_OK(status)) {
307 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
308 return werror_to_ntstatus(status);
311 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
312 for (i=0; i < objs->num_objects; i++) {
313 struct ldb_ldif ldif;
314 fprintf(stdout, "#\n");
315 ldif.changetype = LDB_CHANGETYPE_NONE;
316 ldif.msg = objs->objects[i].msg;
317 ldb_ldif_write_file(s->ldb, stdout, &ldif);
318 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
322 msg = ldb_msg_new(objs);
323 NT_STATUS_HAVE_NO_MEMORY(msg);
324 msg->dn = objs->partition_dn;
326 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
327 if (!W_ERROR_IS_OK(status)) {
328 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
329 return werror_to_ntstatus(status);
332 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
333 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
334 if (ret != LDB_SUCCESS) {
335 return NT_STATUS_FOOBAR;
337 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
339 ret = ldb_modify(s->ldb, msg);
340 if (ret != LDB_SUCCESS) {
341 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
342 return NT_STATUS_FOOBAR;
345 talloc_free(s_dsa);
346 talloc_free(objs);
348 /* We must set these up to ensure the replMetaData is written
349 * correctly, before our NTDS Settings entry is replicated */
350 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
351 if (!ok) {
352 DEBUG(0,("Failed to set cached ntds invocationId\n"));
353 return NT_STATUS_FOOBAR;
355 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
356 if (!ok) {
357 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
358 return NT_STATUS_FOOBAR;
361 s->schema = dsdb_get_schema(s->ldb);
362 if (!s->schema) {
363 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
364 return NT_STATUS_FOOBAR;
367 return NT_STATUS_OK;
370 static NTSTATUS vampire_schema_chunk(void *private_data,
371 const struct libnet_BecomeDC_StoreChunk *c)
373 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
374 WERROR status;
375 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
376 uint32_t nc_object_count;
377 uint32_t object_count;
378 struct drsuapi_DsReplicaObjectListItemEx *first_object;
379 struct drsuapi_DsReplicaObjectListItemEx *cur;
380 uint32_t nc_linked_attributes_count;
381 uint32_t linked_attributes_count;
382 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
384 switch (c->ctr_level) {
385 case 1:
386 mapping_ctr = &c->ctr1->mapping_ctr;
387 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
388 object_count = c->ctr1->object_count;
389 first_object = c->ctr1->first_object;
390 nc_linked_attributes_count = 0;
391 linked_attributes_count = 0;
392 linked_attributes = NULL;
393 break;
394 case 6:
395 mapping_ctr = &c->ctr6->mapping_ctr;
396 nc_object_count = c->ctr6->nc_object_count;
397 object_count = c->ctr6->object_count;
398 first_object = c->ctr6->first_object;
399 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
400 linked_attributes_count = c->ctr6->linked_attributes_count;
401 linked_attributes = c->ctr6->linked_attributes;
402 break;
403 default:
404 return NT_STATUS_INVALID_PARAMETER;
407 if (nc_object_count) {
408 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
409 c->partition->nc.dn, object_count, nc_object_count,
410 linked_attributes_count, nc_linked_attributes_count));
411 } else {
412 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u\n",
413 c->partition->nc.dn, object_count, linked_attributes_count));
416 if (!s->schema) {
417 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
419 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
421 status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
422 if (!W_ERROR_IS_OK(status)) {
423 return werror_to_ntstatus(status);
426 s->schema = s->self_made_schema;
427 } else {
428 status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
429 if (!W_ERROR_IS_OK(status)) {
430 return werror_to_ntstatus(status);
434 if (!s->schema_part.first_object) {
435 s->schema_part.object_count = object_count;
436 s->schema_part.first_object = talloc_steal(s, first_object);
437 } else {
438 s->schema_part.object_count += object_count;
439 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
440 first_object);
442 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
443 s->schema_part.last_object = cur;
445 if (!c->partition->more_data) {
446 return vampire_apply_schema(s, c);
449 return NT_STATUS_OK;
452 static NTSTATUS vampire_store_chunk(void *private_data,
453 const struct libnet_BecomeDC_StoreChunk *c)
455 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
456 WERROR status;
457 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
458 uint32_t nc_object_count;
459 uint32_t object_count;
460 struct drsuapi_DsReplicaObjectListItemEx *first_object;
461 uint32_t nc_linked_attributes_count;
462 uint32_t linked_attributes_count;
463 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
464 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
465 struct dsdb_extended_replicated_objects *objs;
466 struct repsFromTo1 *s_dsa;
467 char *tmp_dns_name;
468 uint32_t i;
469 uint64_t seq_num;
471 s_dsa = talloc_zero(s, struct repsFromTo1);
472 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
473 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
474 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
476 switch (c->ctr_level) {
477 case 1:
478 mapping_ctr = &c->ctr1->mapping_ctr;
479 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
480 object_count = c->ctr1->object_count;
481 first_object = c->ctr1->first_object;
482 nc_linked_attributes_count = 0;
483 linked_attributes_count = 0;
484 linked_attributes = NULL;
485 s_dsa->highwatermark = c->ctr1->new_highwatermark;
486 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
487 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
488 uptodateness_vector = NULL; /* TODO: map it */
489 break;
490 case 6:
491 mapping_ctr = &c->ctr6->mapping_ctr;
492 nc_object_count = c->ctr6->nc_object_count;
493 object_count = c->ctr6->object_count;
494 first_object = c->ctr6->first_object;
495 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
496 linked_attributes_count = c->ctr6->linked_attributes_count;
497 linked_attributes = c->ctr6->linked_attributes;
498 s_dsa->highwatermark = c->ctr6->new_highwatermark;
499 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
500 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
501 uptodateness_vector = c->ctr6->uptodateness_vector;
502 break;
503 default:
504 return NT_STATUS_INVALID_PARAMETER;
507 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
508 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
509 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
510 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
512 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
513 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
514 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
515 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
516 s_dsa->other_info->dns_name = tmp_dns_name;
518 /* we want to show a count per partition */
519 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
520 s->total_objects = 0;
521 talloc_free(s->last_partition);
522 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
524 s->total_objects += object_count;
526 if (nc_object_count) {
527 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
528 c->partition->nc.dn, s->total_objects, nc_object_count,
529 linked_attributes_count, nc_linked_attributes_count));
530 } else {
531 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u\n",
532 c->partition->nc.dn, s->total_objects, linked_attributes_count));
536 status = dsdb_extended_replicated_objects_commit(s->ldb,
537 c->partition->nc.dn,
538 mapping_ctr,
539 object_count,
540 first_object,
541 linked_attributes_count,
542 linked_attributes,
543 s_dsa,
544 uptodateness_vector,
545 c->gensec_skey,
546 s, &objs, &seq_num);
547 if (!W_ERROR_IS_OK(status)) {
548 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
549 return werror_to_ntstatus(status);
552 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
553 for (i=0; i < objs->num_objects; i++) {
554 struct ldb_ldif ldif;
555 fprintf(stdout, "#\n");
556 ldif.changetype = LDB_CHANGETYPE_NONE;
557 ldif.msg = objs->objects[i].msg;
558 ldb_ldif_write_file(s->ldb, stdout, &ldif);
559 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
562 talloc_free(s_dsa);
563 talloc_free(objs);
565 for (i=0; i < linked_attributes_count; i++) {
566 const struct dsdb_attribute *sa;
568 if (!linked_attributes[i].identifier) {
569 return NT_STATUS_FOOBAR;
572 if (!linked_attributes[i].value.blob) {
573 return NT_STATUS_FOOBAR;
576 sa = dsdb_attribute_by_attributeID_id(s->schema,
577 linked_attributes[i].attid);
578 if (!sa) {
579 return NT_STATUS_FOOBAR;
582 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
583 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
584 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
585 dump_data(0,
586 linked_attributes[i].value.blob->data,
587 linked_attributes[i].value.blob->length);
591 return NT_STATUS_OK;
594 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
595 struct libnet_Vampire *r)
597 struct libnet_JoinDomain *join;
598 struct libnet_set_join_secrets *set_secrets;
599 struct libnet_BecomeDC b;
600 struct vampire_state *s;
601 struct ldb_message *msg;
602 int ldb_ret;
603 uint32_t i;
604 NTSTATUS status;
606 const char *account_name;
607 const char *netbios_name;
609 r->out.error_string = NULL;
611 s = talloc_zero(mem_ctx, struct vampire_state);
612 if (!s) {
613 return NT_STATUS_NO_MEMORY;
616 s->lp_ctx = ctx->lp_ctx;
617 s->event_ctx = ctx->event_ctx;
619 join = talloc_zero(s, struct libnet_JoinDomain);
620 if (!join) {
621 return NT_STATUS_NO_MEMORY;
624 if (r->in.netbios_name != NULL) {
625 netbios_name = r->in.netbios_name;
626 } else {
627 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
628 if (!netbios_name) {
629 r->out.error_string = NULL;
630 talloc_free(s);
631 return NT_STATUS_NO_MEMORY;
635 account_name = talloc_asprintf(join, "%s$", netbios_name);
636 if (!account_name) {
637 r->out.error_string = NULL;
638 talloc_free(s);
639 return NT_STATUS_NO_MEMORY;
642 join->in.domain_name = r->in.domain_name;
643 join->in.account_name = account_name;
644 join->in.netbios_name = netbios_name;
645 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
646 join->in.acct_type = ACB_WSTRUST;
647 join->in.recreate_account = false;
648 status = libnet_JoinDomain(ctx, join, join);
649 if (!NT_STATUS_IS_OK(status)) {
650 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
651 talloc_free(s);
652 return status;
655 s->join = join;
657 s->targetdir = r->in.targetdir;
659 ZERO_STRUCT(b);
660 b.in.domain_dns_name = join->out.realm;
661 b.in.domain_netbios_name = join->out.domain_name;
662 b.in.domain_sid = join->out.domain_sid;
663 b.in.source_dsa_address = join->out.samr_binding->host;
664 b.in.dest_dsa_netbios_name = netbios_name;
666 b.in.callbacks.private_data = s;
667 b.in.callbacks.check_options = vampire_check_options;
668 b.in.callbacks.prepare_db = vampire_prepare_db;
669 b.in.callbacks.schema_chunk = vampire_schema_chunk;
670 b.in.callbacks.config_chunk = vampire_store_chunk;
671 b.in.callbacks.domain_chunk = vampire_store_chunk;
673 status = libnet_BecomeDC(ctx, s, &b);
674 if (!NT_STATUS_IS_OK(status)) {
675 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
676 talloc_free(s);
677 return status;
680 msg = ldb_msg_new(s);
681 if (!msg) {
682 printf("ldb_msg_new() failed\n");
683 talloc_free(s);
684 return NT_STATUS_NO_MEMORY;
686 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
687 if (!msg->dn) {
688 printf("ldb_msg_new(@ROOTDSE) failed\n");
689 talloc_free(s);
690 return NT_STATUS_NO_MEMORY;
693 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
694 if (ldb_ret != LDB_SUCCESS) {
695 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
696 talloc_free(s);
697 return NT_STATUS_NO_MEMORY;
700 for (i=0; i < msg->num_elements; i++) {
701 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
704 printf("mark ROOTDSE with isSynchronized=TRUE\n");
705 ldb_ret = ldb_modify(s->ldb, msg);
706 if (ldb_ret != LDB_SUCCESS) {
707 printf("ldb_modify() failed: %d\n", ldb_ret);
708 talloc_free(s);
709 return NT_STATUS_INTERNAL_DB_ERROR;
712 /* commit the transaction - this commits all the changes in
713 the ldb from the whole vampire. Note that this commit
714 triggers the writing of the linked attribute backlinks.
716 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
717 printf("Failed to commit vampire transaction\n");
718 return NT_STATUS_INTERNAL_DB_ERROR;
721 set_secrets = talloc_zero(s, struct libnet_set_join_secrets);
722 if (!set_secrets) {
723 return NT_STATUS_NO_MEMORY;
726 set_secrets->in.domain_name = join->out.domain_name;
727 set_secrets->in.realm = join->out.realm;
728 set_secrets->in.account_name = account_name;
729 set_secrets->in.netbios_name = netbios_name;
730 set_secrets->in.join_type = SEC_CHAN_BDC;
731 set_secrets->in.join_password = join->out.join_password;
732 set_secrets->in.kvno = join->out.kvno;
733 set_secrets->in.domain_sid = join->out.domain_sid;
735 status = libnet_set_join_secrets(ctx, set_secrets, set_secrets);
736 if (!NT_STATUS_IS_OK(status)) {
737 r->out.error_string = talloc_steal(mem_ctx, set_secrets->out.error_string);
738 talloc_free(s);
739 return status;
742 r->out.domain_name = talloc_steal(r, join->out.domain_name);
743 r->out.domain_sid = talloc_steal(r, join->out.domain_sid);
744 talloc_free(s);
746 return NT_STATUS_OK;