s3-spnego: fix memleak in spnego_parse_auth().
[Samba.git] / source4 / libnet / libnet_vampire.c
blobb7b49d8ba5316bf89082207474f902be5c831d68
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"
41 #include "libcli/security/dom_sid.h"
43 /*
44 List of tasks vampire.py must perform:
45 - Domain Join
46 - but don't write the secrets.ldb
47 - results for this should be enough to handle the provision
48 - if vampire method is samsync
49 - Provision using these results
50 - do we still want to support this NT4 technology?
51 - Start samsync with libnet code
52 - provision in the callback
53 - Write out the secrets database, using the code from libnet_Join
56 struct vampire_state {
57 const char *netbios_name;
58 struct libnet_JoinDomain *join;
59 struct cli_credentials *machine_account;
60 struct dsdb_schema *self_made_schema;
61 const struct dsdb_schema *schema;
63 struct ldb_context *ldb;
65 struct {
66 uint32_t object_count;
67 struct drsuapi_DsReplicaObjectListItemEx *first_object;
68 struct drsuapi_DsReplicaObjectListItemEx *last_object;
69 } schema_part;
71 const char *targetdir;
73 struct loadparm_context *lp_ctx;
74 struct tevent_context *event_ctx;
75 unsigned total_objects;
76 char *last_partition;
79 static NTSTATUS vampire_prepare_db(void *private_data,
80 const struct libnet_BecomeDC_PrepareDB *p)
82 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
83 struct provision_settings settings;
84 struct provision_result result;
85 NTSTATUS status;
87 ZERO_STRUCT(settings);
88 settings.site_name = p->dest_dsa->site_name;
89 settings.root_dn_str = p->forest->root_dn_str;
90 settings.domain_dn_str = p->domain->dn_str;
91 settings.config_dn_str = p->forest->config_dn_str;
92 settings.schema_dn_str = p->forest->schema_dn_str;
93 settings.netbios_name = p->dest_dsa->netbios_name;
94 settings.realm = s->join->out.realm;
95 settings.domain = s->join->out.domain_name;
96 settings.server_dn_str = p->dest_dsa->server_dn_str;
97 settings.machine_password = generate_random_str(s, 16);
98 settings.targetdir = s->targetdir;
100 status = provision_bare(s, s->lp_ctx, &settings, &result);
102 if (!NT_STATUS_IS_OK(status)) {
103 return status;
106 s->ldb = result.samdb;
107 s->lp_ctx = result.lp_ctx;
109 /* wrap the entire vapire operation in a transaction. This
110 isn't just cosmetic - we use this to ensure that linked
111 attribute back links are added at the end by relying on a
112 transaction commit hook in the linked attributes module. We
113 need to do this as the order of objects coming from the
114 server is not sufficiently deterministic to know that the
115 record that a backlink needs to be created in has itself
116 been created before the object containing the forward link
117 has come over the wire */
118 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
119 return NT_STATUS_FOOBAR;
122 return NT_STATUS_OK;
127 static NTSTATUS vampire_check_options(void *private_data,
128 const struct libnet_BecomeDC_CheckOptions *o)
130 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
132 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
133 s->netbios_name,
134 o->domain->netbios_name, o->domain->dns_name));
136 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
137 o->source_dsa->dns_name, o->source_dsa->site_name));
139 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
140 "\tschema object_version[%u]\n"
141 "\tdomain behavior_version[%u]\n"
142 "\tdomain w2k3_update_revision[%u]\n",
143 o->forest->crossref_behavior_version,
144 o->forest->schema_object_version,
145 o->domain->behavior_version,
146 o->domain->w2k3_update_revision));
148 return NT_STATUS_OK;
151 static NTSTATUS vampire_apply_schema(struct vampire_state *s,
152 const struct libnet_BecomeDC_StoreChunk *c)
154 WERROR status;
155 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
156 uint32_t object_count;
157 struct drsuapi_DsReplicaObjectListItemEx *first_object;
158 struct drsuapi_DsReplicaObjectListItemEx *cur;
159 uint32_t linked_attributes_count;
160 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
161 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
162 struct dsdb_extended_replicated_objects *objs;
163 struct repsFromTo1 *s_dsa;
164 char *tmp_dns_name;
165 struct ldb_message *msg;
166 struct ldb_val prefixMap_val;
167 struct ldb_message_element *prefixMap_el;
168 struct ldb_val schemaInfo_val;
169 uint32_t i;
170 int ret;
171 bool ok;
172 uint64_t seq_num;
174 DEBUG(0,("Analyze and apply schema objects\n"));
176 s_dsa = talloc_zero(s, struct repsFromTo1);
177 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
178 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
179 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
181 switch (c->ctr_level) {
182 case 1:
183 mapping_ctr = &c->ctr1->mapping_ctr;
184 object_count = s->schema_part.object_count;
185 first_object = s->schema_part.first_object;
186 linked_attributes_count = 0;
187 linked_attributes = NULL;
188 s_dsa->highwatermark = c->ctr1->new_highwatermark;
189 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
190 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
191 uptodateness_vector = NULL; /* TODO: map it */
192 break;
193 case 6:
194 mapping_ctr = &c->ctr6->mapping_ctr;
195 object_count = s->schema_part.object_count;
196 first_object = s->schema_part.first_object;
197 linked_attributes_count = c->ctr6->linked_attributes_count;
198 linked_attributes = c->ctr6->linked_attributes;
199 s_dsa->highwatermark = c->ctr6->new_highwatermark;
200 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
201 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
202 uptodateness_vector = c->ctr6->uptodateness_vector;
203 break;
204 default:
205 return NT_STATUS_INVALID_PARAMETER;
208 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
209 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
210 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
211 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
213 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
214 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
215 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
216 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
217 s_dsa->other_info->dns_name = tmp_dns_name;
219 for (cur = first_object; cur; cur = cur->next_object) {
220 bool is_attr = false;
221 bool is_class = false;
223 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
224 struct drsuapi_DsReplicaAttribute *a;
225 uint32_t j;
226 const char *oid = NULL;
228 a = &cur->object.attribute_ctr.attributes[i];
229 status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
230 if (!W_ERROR_IS_OK(status)) {
231 return werror_to_ntstatus(status);
234 switch (a->attid) {
235 case DRSUAPI_ATTRIBUTE_objectClass:
236 for (j=0; j < a->value_ctr.num_values; j++) {
237 uint32_t val = 0xFFFFFFFF;
239 if (a->value_ctr.values[j].blob
240 && a->value_ctr.values[j].blob->length == 4) {
241 val = IVAL(a->value_ctr.values[j].blob->data,0);
244 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
245 is_attr = true;
247 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
248 is_class = true;
252 break;
253 default:
254 break;
258 if (is_attr) {
259 struct dsdb_attribute *sa;
261 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
262 NT_STATUS_HAVE_NO_MEMORY(sa);
264 status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
265 if (!W_ERROR_IS_OK(status)) {
266 return werror_to_ntstatus(status);
269 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
272 if (is_class) {
273 struct dsdb_class *sc;
275 sc = talloc_zero(s->self_made_schema, struct dsdb_class);
276 NT_STATUS_HAVE_NO_MEMORY(sc);
278 status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
279 if (!W_ERROR_IS_OK(status)) {
280 return werror_to_ntstatus(status);
283 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
287 /* attach the schema to the ldb */
288 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
289 if (ret != LDB_SUCCESS) {
290 return NT_STATUS_FOOBAR;
292 /* we don't want to access the self made schema anymore */
293 s->self_made_schema = NULL;
294 s->schema = dsdb_get_schema(s->ldb);
296 status = dsdb_extended_replicated_objects_commit(s->ldb,
297 c->partition->nc.dn,
298 mapping_ctr,
299 object_count,
300 first_object,
301 linked_attributes_count,
302 linked_attributes,
303 s_dsa,
304 uptodateness_vector,
305 c->gensec_skey,
306 s, &objs, &seq_num);
307 if (!W_ERROR_IS_OK(status)) {
308 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
309 return werror_to_ntstatus(status);
312 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
313 for (i=0; i < objs->num_objects; i++) {
314 struct ldb_ldif ldif;
315 fprintf(stdout, "#\n");
316 ldif.changetype = LDB_CHANGETYPE_NONE;
317 ldif.msg = objs->objects[i].msg;
318 ldb_ldif_write_file(s->ldb, stdout, &ldif);
319 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
323 msg = ldb_msg_new(objs);
324 NT_STATUS_HAVE_NO_MEMORY(msg);
325 msg->dn = objs->partition_dn;
327 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
328 if (!W_ERROR_IS_OK(status)) {
329 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
330 return werror_to_ntstatus(status);
333 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
334 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
335 if (ret != LDB_SUCCESS) {
336 return NT_STATUS_FOOBAR;
338 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
340 ret = ldb_modify(s->ldb, msg);
341 if (ret != LDB_SUCCESS) {
342 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
343 return NT_STATUS_FOOBAR;
346 talloc_free(s_dsa);
347 talloc_free(objs);
349 /* We must set these up to ensure the replMetaData is written
350 * correctly, before our NTDS Settings entry is replicated */
351 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
352 if (!ok) {
353 DEBUG(0,("Failed to set cached ntds invocationId\n"));
354 return NT_STATUS_FOOBAR;
356 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
357 if (!ok) {
358 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
359 return NT_STATUS_FOOBAR;
362 s->schema = dsdb_get_schema(s->ldb);
363 if (!s->schema) {
364 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
365 return NT_STATUS_FOOBAR;
368 return NT_STATUS_OK;
371 static NTSTATUS vampire_schema_chunk(void *private_data,
372 const struct libnet_BecomeDC_StoreChunk *c)
374 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
375 WERROR status;
376 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
377 uint32_t nc_object_count;
378 uint32_t object_count;
379 struct drsuapi_DsReplicaObjectListItemEx *first_object;
380 struct drsuapi_DsReplicaObjectListItemEx *cur;
381 uint32_t nc_linked_attributes_count;
382 uint32_t linked_attributes_count;
383 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
385 switch (c->ctr_level) {
386 case 1:
387 mapping_ctr = &c->ctr1->mapping_ctr;
388 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
389 object_count = c->ctr1->object_count;
390 first_object = c->ctr1->first_object;
391 nc_linked_attributes_count = 0;
392 linked_attributes_count = 0;
393 linked_attributes = NULL;
394 break;
395 case 6:
396 mapping_ctr = &c->ctr6->mapping_ctr;
397 nc_object_count = c->ctr6->nc_object_count;
398 object_count = c->ctr6->object_count;
399 first_object = c->ctr6->first_object;
400 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
401 linked_attributes_count = c->ctr6->linked_attributes_count;
402 linked_attributes = c->ctr6->linked_attributes;
403 break;
404 default:
405 return NT_STATUS_INVALID_PARAMETER;
408 if (nc_object_count) {
409 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
410 c->partition->nc.dn, object_count, nc_object_count,
411 linked_attributes_count, nc_linked_attributes_count));
412 } else {
413 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
414 c->partition->nc.dn, object_count, linked_attributes_count));
417 if (!s->schema) {
418 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
420 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
422 status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
423 if (!W_ERROR_IS_OK(status)) {
424 return werror_to_ntstatus(status);
427 s->schema = s->self_made_schema;
428 } else {
429 status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
430 if (!W_ERROR_IS_OK(status)) {
431 return werror_to_ntstatus(status);
435 if (!s->schema_part.first_object) {
436 s->schema_part.object_count = object_count;
437 s->schema_part.first_object = talloc_steal(s, first_object);
438 } else {
439 s->schema_part.object_count += object_count;
440 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
441 first_object);
443 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
444 s->schema_part.last_object = cur;
446 if (!c->partition->more_data) {
447 return vampire_apply_schema(s, c);
450 return NT_STATUS_OK;
453 static NTSTATUS vampire_store_chunk(void *private_data,
454 const struct libnet_BecomeDC_StoreChunk *c)
456 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
457 WERROR status;
458 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
459 uint32_t nc_object_count;
460 uint32_t object_count;
461 struct drsuapi_DsReplicaObjectListItemEx *first_object;
462 uint32_t nc_linked_attributes_count;
463 uint32_t linked_attributes_count;
464 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
465 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
466 struct dsdb_extended_replicated_objects *objs;
467 struct repsFromTo1 *s_dsa;
468 char *tmp_dns_name;
469 uint32_t i;
470 uint64_t seq_num;
472 s_dsa = talloc_zero(s, struct repsFromTo1);
473 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
474 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
475 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
477 switch (c->ctr_level) {
478 case 1:
479 mapping_ctr = &c->ctr1->mapping_ctr;
480 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
481 object_count = c->ctr1->object_count;
482 first_object = c->ctr1->first_object;
483 nc_linked_attributes_count = 0;
484 linked_attributes_count = 0;
485 linked_attributes = NULL;
486 s_dsa->highwatermark = c->ctr1->new_highwatermark;
487 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
488 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
489 uptodateness_vector = NULL; /* TODO: map it */
490 break;
491 case 6:
492 mapping_ctr = &c->ctr6->mapping_ctr;
493 nc_object_count = c->ctr6->nc_object_count;
494 object_count = c->ctr6->object_count;
495 first_object = c->ctr6->first_object;
496 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
497 linked_attributes_count = c->ctr6->linked_attributes_count;
498 linked_attributes = c->ctr6->linked_attributes;
499 s_dsa->highwatermark = c->ctr6->new_highwatermark;
500 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
501 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
502 uptodateness_vector = c->ctr6->uptodateness_vector;
503 break;
504 default:
505 return NT_STATUS_INVALID_PARAMETER;
508 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
509 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
510 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
511 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
513 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
514 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
515 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
516 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
517 s_dsa->other_info->dns_name = tmp_dns_name;
519 /* we want to show a count per partition */
520 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
521 s->total_objects = 0;
522 talloc_free(s->last_partition);
523 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
525 s->total_objects += object_count;
527 if (nc_object_count) {
528 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
529 c->partition->nc.dn, s->total_objects, nc_object_count,
530 linked_attributes_count, nc_linked_attributes_count));
531 } else {
532 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
533 c->partition->nc.dn, s->total_objects, linked_attributes_count));
537 status = dsdb_extended_replicated_objects_commit(s->ldb,
538 c->partition->nc.dn,
539 mapping_ctr,
540 object_count,
541 first_object,
542 linked_attributes_count,
543 linked_attributes,
544 s_dsa,
545 uptodateness_vector,
546 c->gensec_skey,
547 s, &objs, &seq_num);
548 if (!W_ERROR_IS_OK(status)) {
549 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
550 return werror_to_ntstatus(status);
553 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
554 for (i=0; i < objs->num_objects; i++) {
555 struct ldb_ldif ldif;
556 fprintf(stdout, "#\n");
557 ldif.changetype = LDB_CHANGETYPE_NONE;
558 ldif.msg = objs->objects[i].msg;
559 ldb_ldif_write_file(s->ldb, stdout, &ldif);
560 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
563 talloc_free(s_dsa);
564 talloc_free(objs);
566 for (i=0; i < linked_attributes_count; i++) {
567 const struct dsdb_attribute *sa;
569 if (!linked_attributes[i].identifier) {
570 return NT_STATUS_FOOBAR;
573 if (!linked_attributes[i].value.blob) {
574 return NT_STATUS_FOOBAR;
577 sa = dsdb_attribute_by_attributeID_id(s->schema,
578 linked_attributes[i].attid);
579 if (!sa) {
580 return NT_STATUS_FOOBAR;
583 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
584 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
585 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
586 dump_data(0,
587 linked_attributes[i].value.blob->data,
588 linked_attributes[i].value.blob->length);
592 return NT_STATUS_OK;
595 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
596 struct libnet_Vampire *r)
598 struct libnet_JoinDomain *join;
599 struct provision_store_self_join_settings *set_secrets;
600 struct libnet_BecomeDC b;
601 struct vampire_state *s;
602 struct ldb_message *msg;
603 const char *error_string;
604 int ldb_ret;
605 uint32_t i;
606 NTSTATUS status;
608 const char *account_name;
609 const char *netbios_name;
611 r->out.error_string = NULL;
613 s = talloc_zero(mem_ctx, struct vampire_state);
614 if (!s) {
615 return NT_STATUS_NO_MEMORY;
618 s->lp_ctx = ctx->lp_ctx;
619 s->event_ctx = ctx->event_ctx;
621 join = talloc_zero(s, struct libnet_JoinDomain);
622 if (!join) {
623 return NT_STATUS_NO_MEMORY;
626 if (r->in.netbios_name != NULL) {
627 netbios_name = r->in.netbios_name;
628 } else {
629 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
630 if (!netbios_name) {
631 r->out.error_string = NULL;
632 talloc_free(s);
633 return NT_STATUS_NO_MEMORY;
637 account_name = talloc_asprintf(join, "%s$", netbios_name);
638 if (!account_name) {
639 r->out.error_string = NULL;
640 talloc_free(s);
641 return NT_STATUS_NO_MEMORY;
644 join->in.domain_name = r->in.domain_name;
645 join->in.account_name = account_name;
646 join->in.netbios_name = netbios_name;
647 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
648 join->in.acct_type = ACB_WSTRUST;
649 join->in.recreate_account = false;
650 status = libnet_JoinDomain(ctx, join, join);
651 if (!NT_STATUS_IS_OK(status)) {
652 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
653 talloc_free(s);
654 return status;
657 s->join = join;
659 s->targetdir = r->in.targetdir;
661 ZERO_STRUCT(b);
662 b.in.domain_dns_name = join->out.realm;
663 b.in.domain_netbios_name = join->out.domain_name;
664 b.in.domain_sid = join->out.domain_sid;
665 b.in.source_dsa_address = join->out.samr_binding->host;
666 b.in.dest_dsa_netbios_name = netbios_name;
668 b.in.callbacks.private_data = s;
669 b.in.callbacks.check_options = vampire_check_options;
670 b.in.callbacks.prepare_db = vampire_prepare_db;
671 b.in.callbacks.schema_chunk = vampire_schema_chunk;
672 b.in.callbacks.config_chunk = vampire_store_chunk;
673 b.in.callbacks.domain_chunk = vampire_store_chunk;
675 status = libnet_BecomeDC(ctx, s, &b);
676 if (!NT_STATUS_IS_OK(status)) {
677 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
678 talloc_free(s);
679 return status;
682 msg = ldb_msg_new(s);
683 if (!msg) {
684 printf("ldb_msg_new() failed\n");
685 talloc_free(s);
686 return NT_STATUS_NO_MEMORY;
688 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
689 if (!msg->dn) {
690 printf("ldb_msg_new(@ROOTDSE) failed\n");
691 talloc_free(s);
692 return NT_STATUS_NO_MEMORY;
695 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
696 if (ldb_ret != LDB_SUCCESS) {
697 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
698 talloc_free(s);
699 return NT_STATUS_NO_MEMORY;
702 for (i=0; i < msg->num_elements; i++) {
703 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
706 printf("mark ROOTDSE with isSynchronized=TRUE\n");
707 ldb_ret = ldb_modify(s->ldb, msg);
708 if (ldb_ret != LDB_SUCCESS) {
709 printf("ldb_modify() failed: %d\n", ldb_ret);
710 talloc_free(s);
711 return NT_STATUS_INTERNAL_DB_ERROR;
714 /* prepare the transaction - this prepares to commit all the changes in
715 the ldb from the whole vampire. Note that this
716 triggers the writing of the linked attribute backlinks.
718 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
719 printf("Failed to prepare_commit vampire transaction\n");
720 return NT_STATUS_INTERNAL_DB_ERROR;
723 set_secrets = talloc(s, struct provision_store_self_join_settings);
724 if (!set_secrets) {
725 r->out.error_string = NULL;
726 talloc_free(s);
727 return NT_STATUS_NO_MEMORY;
730 ZERO_STRUCTP(set_secrets);
731 set_secrets->domain_name = join->out.domain_name;
732 set_secrets->realm = join->out.realm;
733 set_secrets->account_name = account_name;
734 set_secrets->netbios_name = netbios_name;
735 set_secrets->secure_channel_type = SEC_CHAN_BDC;
736 set_secrets->machine_password = join->out.join_password;
737 set_secrets->key_version_number = join->out.kvno;
738 set_secrets->domain_sid = join->out.domain_sid;
740 status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
741 if (!NT_STATUS_IS_OK(status)) {
742 r->out.error_string = talloc_steal(mem_ctx, error_string);
743 talloc_free(s);
744 return status;
747 r->out.domain_name = talloc_steal(r, join->out.domain_name);
748 r->out.domain_sid = dom_sid_dup(r, join->out.domain_sid);
750 /* commit the transaction now we know the secrets were written
751 * out properly
753 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
754 printf("Failed to commit vampire transaction\n");
755 return NT_STATUS_INTERNAL_DB_ERROR;
758 talloc_free(s);
760 return NT_STATUS_OK;