Do not redefine strupr
[Samba/fernandojvsilva.git] / source4 / libnet / libnet_vampire.c
blobd8b890e5b4e456dc022cccc6c9684f15815cc82c
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;
76 static NTSTATUS vampire_prepare_db(void *private_data,
77 const struct libnet_BecomeDC_PrepareDB *p)
79 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
80 struct provision_settings settings;
81 struct provision_result result;
82 NTSTATUS status;
84 ZERO_STRUCT(settings);
85 settings.site_name = p->dest_dsa->site_name;
86 settings.root_dn_str = p->forest->root_dn_str;
87 settings.domain_dn_str = p->domain->dn_str;
88 settings.config_dn_str = p->forest->config_dn_str;
89 settings.schema_dn_str = p->forest->schema_dn_str;
90 settings.netbios_name = p->dest_dsa->netbios_name;
91 settings.realm = s->join->out.realm;
92 settings.domain = s->join->out.domain_name;
93 settings.server_dn_str = p->dest_dsa->server_dn_str;
94 settings.machine_password = generate_random_str(s, 16);
95 settings.targetdir = s->targetdir;
97 status = provision_bare(s, s->lp_ctx, &settings, &result);
99 if (!NT_STATUS_IS_OK(status)) {
100 return status;
103 s->ldb = result.samdb;
104 s->lp_ctx = result.lp_ctx;
106 /* wrap the entire vapire operation in a transaction. This
107 isn't just cosmetic - we use this to ensure that linked
108 attribute back links are added at the end by relying on a
109 transaction commit hook in the linked attributes module. We
110 need to do this as the order of objects coming from the
111 server is not sufficiently deterministic to know that the
112 record that a backlink needs to be created in has itself
113 been created before the object containing the forward link
114 has come over the wire */
115 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
116 return NT_STATUS_FOOBAR;
119 return NT_STATUS_OK;
124 static NTSTATUS vampire_check_options(void *private_data,
125 const struct libnet_BecomeDC_CheckOptions *o)
127 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
129 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
130 s->netbios_name,
131 o->domain->netbios_name, o->domain->dns_name));
133 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
134 o->source_dsa->dns_name, o->source_dsa->site_name));
136 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
137 "\tschema object_version[%u]\n"
138 "\tdomain behavior_version[%u]\n"
139 "\tdomain w2k3_update_revision[%u]\n",
140 o->forest->crossref_behavior_version,
141 o->forest->schema_object_version,
142 o->domain->behavior_version,
143 o->domain->w2k3_update_revision));
145 return NT_STATUS_OK;
148 static NTSTATUS vampire_apply_schema(struct vampire_state *s,
149 const struct libnet_BecomeDC_StoreChunk *c)
151 WERROR status;
152 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
153 uint32_t object_count;
154 struct drsuapi_DsReplicaObjectListItemEx *first_object;
155 struct drsuapi_DsReplicaObjectListItemEx *cur;
156 uint32_t linked_attributes_count;
157 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
158 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
159 struct dsdb_extended_replicated_objects *objs;
160 struct repsFromTo1 *s_dsa;
161 char *tmp_dns_name;
162 struct ldb_message *msg;
163 struct ldb_val prefixMap_val;
164 struct ldb_message_element *prefixMap_el;
165 struct ldb_val schemaInfo_val;
166 uint32_t i;
167 int ret;
168 bool ok;
170 DEBUG(0,("Analyze and apply schema objects\n"));
172 s_dsa = talloc_zero(s, struct repsFromTo1);
173 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
174 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
175 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
177 switch (c->ctr_level) {
178 case 1:
179 mapping_ctr = &c->ctr1->mapping_ctr;
180 object_count = s->schema_part.object_count;
181 first_object = s->schema_part.first_object;
182 linked_attributes_count = 0;
183 linked_attributes = NULL;
184 s_dsa->highwatermark = c->ctr1->new_highwatermark;
185 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
186 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
187 uptodateness_vector = NULL; /* TODO: map it */
188 break;
189 case 6:
190 mapping_ctr = &c->ctr6->mapping_ctr;
191 object_count = s->schema_part.object_count;
192 first_object = s->schema_part.first_object;
193 linked_attributes_count = 0; /* TODO: ! */
194 linked_attributes = NULL; /* TODO: ! */;
195 s_dsa->highwatermark = c->ctr6->new_highwatermark;
196 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
197 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
198 uptodateness_vector = c->ctr6->uptodateness_vector;
199 break;
200 default:
201 return NT_STATUS_INVALID_PARAMETER;
204 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
205 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
206 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
207 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
209 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
210 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
211 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
212 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
213 s_dsa->other_info->dns_name = tmp_dns_name;
215 for (cur = first_object; cur; cur = cur->next_object) {
216 bool is_attr = false;
217 bool is_class = false;
219 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
220 struct drsuapi_DsReplicaAttribute *a;
221 uint32_t j;
222 const char *oid = NULL;
224 a = &cur->object.attribute_ctr.attributes[i];
225 status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
226 if (!W_ERROR_IS_OK(status)) {
227 return werror_to_ntstatus(status);
230 switch (a->attid) {
231 case DRSUAPI_ATTRIBUTE_objectClass:
232 for (j=0; j < a->value_ctr.num_values; j++) {
233 uint32_t val = 0xFFFFFFFF;
235 if (a->value_ctr.values[i].blob
236 && a->value_ctr.values[i].blob->length == 4) {
237 val = IVAL(a->value_ctr.values[i].blob->data,0);
240 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
241 is_attr = true;
243 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
244 is_class = true;
248 break;
249 default:
250 break;
254 if (is_attr) {
255 struct dsdb_attribute *sa;
257 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
258 NT_STATUS_HAVE_NO_MEMORY(sa);
260 status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
261 if (!W_ERROR_IS_OK(status)) {
262 return werror_to_ntstatus(status);
265 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
268 if (is_class) {
269 struct dsdb_class *sc;
271 sc = talloc_zero(s->self_made_schema, struct dsdb_class);
272 NT_STATUS_HAVE_NO_MEMORY(sc);
274 status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
275 if (!W_ERROR_IS_OK(status)) {
276 return werror_to_ntstatus(status);
279 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
283 /* attach the schema to the ldb */
284 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
285 if (ret != LDB_SUCCESS) {
286 return NT_STATUS_FOOBAR;
288 /* we don't want to access the self made schema anymore */
289 s->self_made_schema = NULL;
290 s->schema = dsdb_get_schema(s->ldb);
292 status = dsdb_extended_replicated_objects_commit(s->ldb,
293 c->partition->nc.dn,
294 mapping_ctr,
295 object_count,
296 first_object,
297 linked_attributes_count,
298 linked_attributes,
299 s_dsa,
300 uptodateness_vector,
301 c->gensec_skey,
302 s, &objs);
303 if (!W_ERROR_IS_OK(status)) {
304 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
305 return werror_to_ntstatus(status);
308 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
309 for (i=0; i < objs->num_objects; i++) {
310 struct ldb_ldif ldif;
311 fprintf(stdout, "#\n");
312 ldif.changetype = LDB_CHANGETYPE_NONE;
313 ldif.msg = objs->objects[i].msg;
314 ldb_ldif_write_file(s->ldb, stdout, &ldif);
315 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
319 msg = ldb_msg_new(objs);
320 NT_STATUS_HAVE_NO_MEMORY(msg);
321 msg->dn = objs->partition_dn;
323 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
324 if (!W_ERROR_IS_OK(status)) {
325 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
326 return werror_to_ntstatus(status);
329 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
330 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
331 if (ret != LDB_SUCCESS) {
332 return NT_STATUS_FOOBAR;
334 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
336 ret = ldb_modify(s->ldb, msg);
337 if (ret != LDB_SUCCESS) {
338 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
339 return NT_STATUS_FOOBAR;
342 talloc_free(s_dsa);
343 talloc_free(objs);
345 /* We must set these up to ensure the replMetaData is written
346 * correctly, before our NTDS Settings entry is replicated */
347 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
348 if (!ok) {
349 DEBUG(0,("Failed to set cached ntds invocationId\n"));
350 return NT_STATUS_FOOBAR;
352 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
353 if (!ok) {
354 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
355 return NT_STATUS_FOOBAR;
358 s->schema = dsdb_get_schema(s->ldb);
359 if (!s->schema) {
360 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
361 return NT_STATUS_FOOBAR;
364 return NT_STATUS_OK;
367 static NTSTATUS vampire_schema_chunk(void *private_data,
368 const struct libnet_BecomeDC_StoreChunk *c)
370 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
371 WERROR status;
372 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
373 uint32_t nc_object_count;
374 uint32_t object_count;
375 struct drsuapi_DsReplicaObjectListItemEx *first_object;
376 struct drsuapi_DsReplicaObjectListItemEx *cur;
377 uint32_t nc_linked_attributes_count;
378 uint32_t linked_attributes_count;
380 switch (c->ctr_level) {
381 case 1:
382 mapping_ctr = &c->ctr1->mapping_ctr;
383 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
384 object_count = c->ctr1->object_count;
385 first_object = c->ctr1->first_object;
386 nc_linked_attributes_count = 0;
387 linked_attributes_count = 0;
388 break;
389 case 6:
390 mapping_ctr = &c->ctr6->mapping_ctr;
391 nc_object_count = c->ctr6->nc_object_count;
392 object_count = c->ctr6->object_count;
393 first_object = c->ctr6->first_object;
394 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
395 linked_attributes_count = c->ctr6->linked_attributes_count;
396 break;
397 default:
398 return NT_STATUS_INVALID_PARAMETER;
401 if (nc_object_count) {
402 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
403 c->partition->nc.dn, object_count, nc_object_count,
404 linked_attributes_count, nc_linked_attributes_count));
405 } else {
406 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u\n",
407 c->partition->nc.dn, object_count, linked_attributes_count));
410 if (!s->schema) {
411 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
413 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
415 status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
416 if (!W_ERROR_IS_OK(status)) {
417 return werror_to_ntstatus(status);
420 s->schema = s->self_made_schema;
421 } else {
422 status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
423 if (!W_ERROR_IS_OK(status)) {
424 return werror_to_ntstatus(status);
428 if (!s->schema_part.first_object) {
429 s->schema_part.object_count = object_count;
430 s->schema_part.first_object = talloc_steal(s, first_object);
431 } else {
432 s->schema_part.object_count += object_count;
433 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
434 first_object);
436 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
437 s->schema_part.last_object = cur;
439 if (!c->partition->more_data) {
440 return vampire_apply_schema(s, c);
443 return NT_STATUS_OK;
446 static NTSTATUS vampire_store_chunk(void *private_data,
447 const struct libnet_BecomeDC_StoreChunk *c)
449 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
450 WERROR status;
451 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
452 uint32_t nc_object_count;
453 uint32_t object_count;
454 struct drsuapi_DsReplicaObjectListItemEx *first_object;
455 uint32_t nc_linked_attributes_count;
456 uint32_t linked_attributes_count;
457 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
458 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
459 struct dsdb_extended_replicated_objects *objs;
460 struct repsFromTo1 *s_dsa;
461 char *tmp_dns_name;
462 uint32_t i;
464 s_dsa = talloc_zero(s, struct repsFromTo1);
465 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
466 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
467 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
469 switch (c->ctr_level) {
470 case 1:
471 mapping_ctr = &c->ctr1->mapping_ctr;
472 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
473 object_count = c->ctr1->object_count;
474 first_object = c->ctr1->first_object;
475 nc_linked_attributes_count = 0;
476 linked_attributes_count = 0;
477 linked_attributes = NULL;
478 s_dsa->highwatermark = c->ctr1->new_highwatermark;
479 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
480 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
481 uptodateness_vector = NULL; /* TODO: map it */
482 break;
483 case 6:
484 mapping_ctr = &c->ctr6->mapping_ctr;
485 nc_object_count = c->ctr6->nc_object_count;
486 object_count = c->ctr6->object_count;
487 first_object = c->ctr6->first_object;
488 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
489 linked_attributes_count = c->ctr6->linked_attributes_count;
490 linked_attributes = c->ctr6->linked_attributes;
491 s_dsa->highwatermark = c->ctr6->new_highwatermark;
492 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
493 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
494 uptodateness_vector = c->ctr6->uptodateness_vector;
495 break;
496 default:
497 return NT_STATUS_INVALID_PARAMETER;
500 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
501 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
502 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
503 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
505 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
506 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
507 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
508 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
509 s_dsa->other_info->dns_name = tmp_dns_name;
511 if (nc_object_count) {
512 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
513 c->partition->nc.dn, object_count, nc_object_count,
514 linked_attributes_count, nc_linked_attributes_count));
515 } else {
516 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u\n",
517 c->partition->nc.dn, object_count, linked_attributes_count));
520 status = dsdb_extended_replicated_objects_commit(s->ldb,
521 c->partition->nc.dn,
522 mapping_ctr,
523 object_count,
524 first_object,
525 linked_attributes_count,
526 linked_attributes,
527 s_dsa,
528 uptodateness_vector,
529 c->gensec_skey,
530 s, &objs);
531 if (!W_ERROR_IS_OK(status)) {
532 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
533 return werror_to_ntstatus(status);
536 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
537 for (i=0; i < objs->num_objects; i++) {
538 struct ldb_ldif ldif;
539 fprintf(stdout, "#\n");
540 ldif.changetype = LDB_CHANGETYPE_NONE;
541 ldif.msg = objs->objects[i].msg;
542 ldb_ldif_write_file(s->ldb, stdout, &ldif);
543 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
546 talloc_free(s_dsa);
547 talloc_free(objs);
549 for (i=0; i < linked_attributes_count; i++) {
550 const struct dsdb_attribute *sa;
552 if (!linked_attributes[i].identifier) {
553 return NT_STATUS_FOOBAR;
556 if (!linked_attributes[i].value.blob) {
557 return NT_STATUS_FOOBAR;
560 sa = dsdb_attribute_by_attributeID_id(s->schema,
561 linked_attributes[i].attid);
562 if (!sa) {
563 return NT_STATUS_FOOBAR;
566 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
567 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
568 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
569 dump_data(0,
570 linked_attributes[i].value.blob->data,
571 linked_attributes[i].value.blob->length);
575 return NT_STATUS_OK;
578 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
579 struct libnet_Vampire *r)
581 struct libnet_JoinDomain *join;
582 struct libnet_set_join_secrets *set_secrets;
583 struct libnet_BecomeDC b;
584 struct vampire_state *s;
585 struct ldb_message *msg;
586 int ldb_ret;
587 uint32_t i;
588 NTSTATUS status;
590 const char *account_name;
591 const char *netbios_name;
593 r->out.error_string = NULL;
595 s = talloc_zero(mem_ctx, struct vampire_state);
596 if (!s) {
597 return NT_STATUS_NO_MEMORY;
600 s->lp_ctx = ctx->lp_ctx;
601 s->event_ctx = ctx->event_ctx;
603 join = talloc_zero(s, struct libnet_JoinDomain);
604 if (!join) {
605 return NT_STATUS_NO_MEMORY;
608 if (r->in.netbios_name != NULL) {
609 netbios_name = r->in.netbios_name;
610 } else {
611 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
612 if (!netbios_name) {
613 r->out.error_string = NULL;
614 talloc_free(s);
615 return NT_STATUS_NO_MEMORY;
619 account_name = talloc_asprintf(join, "%s$", netbios_name);
620 if (!account_name) {
621 r->out.error_string = NULL;
622 talloc_free(s);
623 return NT_STATUS_NO_MEMORY;
626 join->in.domain_name = r->in.domain_name;
627 join->in.account_name = account_name;
628 join->in.netbios_name = netbios_name;
629 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
630 join->in.acct_type = ACB_WSTRUST;
631 join->in.recreate_account = false;
632 status = libnet_JoinDomain(ctx, join, join);
633 if (!NT_STATUS_IS_OK(status)) {
634 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
635 talloc_free(s);
636 return status;
639 s->join = join;
641 s->targetdir = r->in.targetdir;
643 ZERO_STRUCT(b);
644 b.in.domain_dns_name = join->out.realm;
645 b.in.domain_netbios_name = join->out.domain_name;
646 b.in.domain_sid = join->out.domain_sid;
647 b.in.source_dsa_address = join->out.samr_binding->host;
648 b.in.dest_dsa_netbios_name = netbios_name;
650 b.in.callbacks.private_data = s;
651 b.in.callbacks.check_options = vampire_check_options;
652 b.in.callbacks.prepare_db = vampire_prepare_db;
653 b.in.callbacks.schema_chunk = vampire_schema_chunk;
654 b.in.callbacks.config_chunk = vampire_store_chunk;
655 b.in.callbacks.domain_chunk = vampire_store_chunk;
657 status = libnet_BecomeDC(ctx, s, &b);
658 if (!NT_STATUS_IS_OK(status)) {
659 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
660 talloc_free(s);
661 return status;
664 msg = ldb_msg_new(s);
665 if (!msg) {
666 printf("ldb_msg_new() failed\n");
667 talloc_free(s);
668 return NT_STATUS_NO_MEMORY;
670 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
671 if (!msg->dn) {
672 printf("ldb_msg_new(@ROOTDSE) failed\n");
673 talloc_free(s);
674 return NT_STATUS_NO_MEMORY;
677 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
678 if (ldb_ret != LDB_SUCCESS) {
679 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
680 talloc_free(s);
681 return NT_STATUS_NO_MEMORY;
684 for (i=0; i < msg->num_elements; i++) {
685 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
688 printf("mark ROOTDSE with isSynchronized=TRUE\n");
689 ldb_ret = ldb_modify(s->ldb, msg);
690 if (ldb_ret != LDB_SUCCESS) {
691 printf("ldb_modify() failed: %d\n", ldb_ret);
692 talloc_free(s);
693 return NT_STATUS_INTERNAL_DB_ERROR;
696 /* commit the transaction - this commits all the changes in
697 the ldb from the whole vampire. Note that this commit
698 triggers the writing of the linked attribute backlinks.
700 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
701 printf("Failed to commit vampire transaction\n");
702 return NT_STATUS_INTERNAL_DB_ERROR;
705 set_secrets = talloc_zero(s, struct libnet_set_join_secrets);
706 if (!set_secrets) {
707 return NT_STATUS_NO_MEMORY;
710 set_secrets->in.domain_name = join->out.domain_name;
711 set_secrets->in.realm = join->out.realm;
712 set_secrets->in.account_name = account_name;
713 set_secrets->in.netbios_name = netbios_name;
714 set_secrets->in.join_type = SEC_CHAN_BDC;
715 set_secrets->in.join_password = join->out.join_password;
716 set_secrets->in.kvno = join->out.kvno;
717 set_secrets->in.domain_sid = join->out.domain_sid;
719 status = libnet_set_join_secrets(ctx, set_secrets, set_secrets);
720 if (!NT_STATUS_IS_OK(status)) {
721 r->out.error_string = talloc_steal(mem_ctx, set_secrets->out.error_string);
722 talloc_free(s);
723 return status;
726 r->out.domain_name = talloc_steal(r, join->out.domain_name);
727 r->out.domain_sid = talloc_steal(r, join->out.domain_sid);
728 talloc_free(s);
730 return NT_STATUS_OK;