s3-docs: Move -D option to the right paragraph in man winbindd.
[Samba.git] / source4 / libnet / libnet_vampire.c
bloba5c8a8f5d42bfbbbe3b020b2b9ec66436e526d76
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 "auth/credentials/credentials.h"
40 #include "param/param.h"
41 #include "param/provision.h"
42 #include "libcli/security/dom_sid.h"
44 /*
45 List of tasks vampire.py must perform:
46 - Domain Join
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 vampire_state {
58 const char *netbios_name;
59 struct libnet_JoinDomain *join;
60 struct cli_credentials *machine_account;
61 struct dsdb_schema *self_made_schema;
62 const struct dsdb_schema *schema;
64 struct ldb_context *ldb;
66 struct {
67 uint32_t object_count;
68 struct drsuapi_DsReplicaObjectListItemEx *first_object;
69 struct drsuapi_DsReplicaObjectListItemEx *last_object;
70 } schema_part;
72 const char *targetdir;
74 struct loadparm_context *lp_ctx;
75 struct tevent_context *event_ctx;
76 unsigned total_objects;
77 char *last_partition;
80 static NTSTATUS vampire_prepare_db(void *private_data,
81 const struct libnet_BecomeDC_PrepareDB *p)
83 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
84 struct provision_settings settings;
85 struct provision_result result;
86 NTSTATUS status;
88 ZERO_STRUCT(settings);
89 settings.site_name = p->dest_dsa->site_name;
90 settings.root_dn_str = p->forest->root_dn_str;
91 settings.domain_dn_str = p->domain->dn_str;
92 settings.config_dn_str = p->forest->config_dn_str;
93 settings.schema_dn_str = p->forest->schema_dn_str;
94 settings.netbios_name = p->dest_dsa->netbios_name;
95 settings.realm = s->join->out.realm;
96 settings.domain = s->join->out.domain_name;
97 settings.server_dn_str = p->dest_dsa->server_dn_str;
98 settings.machine_password = generate_random_password(s, 16, 255);
99 settings.targetdir = s->targetdir;
101 status = provision_bare(s, s->lp_ctx, &settings, &result);
103 if (!NT_STATUS_IS_OK(status)) {
104 return status;
107 s->ldb = result.samdb;
108 s->lp_ctx = result.lp_ctx;
110 /* wrap the entire vapire operation in a transaction. This
111 isn't just cosmetic - we use this to ensure that linked
112 attribute back links are added at the end by relying on a
113 transaction commit hook in the linked attributes module. We
114 need to do this as the order of objects coming from the
115 server is not sufficiently deterministic to know that the
116 record that a backlink needs to be created in has itself
117 been created before the object containing the forward link
118 has come over the wire */
119 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
120 return NT_STATUS_FOOBAR;
123 return NT_STATUS_OK;
128 static NTSTATUS vampire_check_options(void *private_data,
129 const struct libnet_BecomeDC_CheckOptions *o)
131 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
133 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
134 s->netbios_name,
135 o->domain->netbios_name, o->domain->dns_name));
137 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
138 o->source_dsa->dns_name, o->source_dsa->site_name));
140 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
141 "\tschema object_version[%u]\n"
142 "\tdomain behavior_version[%u]\n"
143 "\tdomain w2k3_update_revision[%u]\n",
144 o->forest->crossref_behavior_version,
145 o->forest->schema_object_version,
146 o->domain->behavior_version,
147 o->domain->w2k3_update_revision));
149 return NT_STATUS_OK;
152 static NTSTATUS vampire_apply_schema(struct vampire_state *s,
153 const struct libnet_BecomeDC_StoreChunk *c)
155 WERROR status;
156 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
157 uint32_t object_count;
158 struct drsuapi_DsReplicaObjectListItemEx *first_object;
159 struct drsuapi_DsReplicaObjectListItemEx *cur;
160 uint32_t linked_attributes_count;
161 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
162 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
163 struct dsdb_extended_replicated_objects *objs;
164 struct repsFromTo1 *s_dsa;
165 char *tmp_dns_name;
166 struct ldb_message *msg;
167 struct ldb_val prefixMap_val;
168 struct ldb_message_element *prefixMap_el;
169 struct ldb_val schemaInfo_val;
170 uint32_t i;
171 int ret;
172 bool ok;
173 uint64_t seq_num;
175 DEBUG(0,("Analyze and apply schema objects\n"));
177 s_dsa = talloc_zero(s, struct repsFromTo1);
178 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
179 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
180 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
182 switch (c->ctr_level) {
183 case 1:
184 mapping_ctr = &c->ctr1->mapping_ctr;
185 object_count = s->schema_part.object_count;
186 first_object = s->schema_part.first_object;
187 linked_attributes_count = 0;
188 linked_attributes = NULL;
189 s_dsa->highwatermark = c->ctr1->new_highwatermark;
190 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
191 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
192 uptodateness_vector = NULL; /* TODO: map it */
193 break;
194 case 6:
195 mapping_ctr = &c->ctr6->mapping_ctr;
196 object_count = s->schema_part.object_count;
197 first_object = s->schema_part.first_object;
198 linked_attributes_count = c->ctr6->linked_attributes_count;
199 linked_attributes = c->ctr6->linked_attributes;
200 s_dsa->highwatermark = c->ctr6->new_highwatermark;
201 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
202 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
203 uptodateness_vector = c->ctr6->uptodateness_vector;
204 break;
205 default:
206 return NT_STATUS_INVALID_PARAMETER;
209 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
210 | DRSUAPI_DRS_INIT_SYNC
211 | DRSUAPI_DRS_PER_SYNC;
212 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
214 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
215 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
216 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
217 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
218 s_dsa->other_info->dns_name = tmp_dns_name;
220 for (cur = first_object; cur; cur = cur->next_object) {
221 bool is_attr = false;
222 bool is_class = false;
224 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
225 struct drsuapi_DsReplicaAttribute *a;
226 uint32_t j;
227 const char *oid = NULL;
229 a = &cur->object.attribute_ctr.attributes[i];
230 status = dsdb_schema_pfm_oid_from_attid(s->self_made_schema->prefixmap,
231 a->attid, s, &oid);
232 if (!W_ERROR_IS_OK(status)) {
233 return werror_to_ntstatus(status);
236 switch (a->attid) {
237 case DRSUAPI_ATTRIBUTE_objectClass:
238 for (j=0; j < a->value_ctr.num_values; j++) {
239 uint32_t val = 0xFFFFFFFF;
241 if (a->value_ctr.values[j].blob
242 && a->value_ctr.values[j].blob->length == 4) {
243 val = IVAL(a->value_ctr.values[j].blob->data,0);
246 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
247 is_attr = true;
249 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
250 is_class = true;
254 break;
255 default:
256 break;
260 if (is_attr) {
261 struct dsdb_attribute *sa;
263 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
264 NT_STATUS_HAVE_NO_MEMORY(sa);
266 status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
267 if (!W_ERROR_IS_OK(status)) {
268 return werror_to_ntstatus(status);
271 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
274 if (is_class) {
275 struct dsdb_class *sc;
277 sc = talloc_zero(s->self_made_schema, struct dsdb_class);
278 NT_STATUS_HAVE_NO_MEMORY(sc);
280 status = dsdb_class_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sc);
281 if (!W_ERROR_IS_OK(status)) {
282 return werror_to_ntstatus(status);
284 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
288 /* attach the schema to the ldb */
289 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
290 if (ret != LDB_SUCCESS) {
291 return NT_STATUS_FOOBAR;
293 /* we don't want to access the self made schema anymore */
294 s->schema = s->self_made_schema;
295 s->self_made_schema = NULL;
297 /* Now convert the schema elements again, using the schema we just imported */
298 status = dsdb_extended_replicated_objects_convert(s->ldb,
299 c->partition->nc.dn,
300 mapping_ctr,
301 object_count,
302 first_object,
303 linked_attributes_count,
304 linked_attributes,
305 s_dsa,
306 uptodateness_vector,
307 c->gensec_skey,
308 s, &objs);
309 if (!W_ERROR_IS_OK(status)) {
310 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
311 return werror_to_ntstatus(status);
314 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
315 for (i=0; i < objs->num_objects; i++) {
316 struct ldb_ldif ldif;
317 fprintf(stdout, "#\n");
318 ldif.changetype = LDB_CHANGETYPE_NONE;
319 ldif.msg = objs->objects[i].msg;
320 ldb_ldif_write_file(s->ldb, stdout, &ldif);
321 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
325 status = dsdb_extended_replicated_objects_commit(s->ldb, objs, &seq_num);
326 if (!W_ERROR_IS_OK(status)) {
327 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
328 return werror_to_ntstatus(status);
331 msg = ldb_msg_new(objs);
332 NT_STATUS_HAVE_NO_MEMORY(msg);
333 msg->dn = objs->partition_dn;
335 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
336 if (!W_ERROR_IS_OK(status)) {
337 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
338 return werror_to_ntstatus(status);
341 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
342 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
343 if (ret != LDB_SUCCESS) {
344 return NT_STATUS_FOOBAR;
346 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
348 ret = ldb_modify(s->ldb, msg);
349 if (ret != LDB_SUCCESS) {
350 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
351 return NT_STATUS_FOOBAR;
354 talloc_free(s_dsa);
355 talloc_free(objs);
357 /* We must set these up to ensure the replMetaData is written
358 * correctly, before our NTDS Settings entry is replicated */
359 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
360 if (!ok) {
361 DEBUG(0,("Failed to set cached ntds invocationId\n"));
362 return NT_STATUS_FOOBAR;
364 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
365 if (!ok) {
366 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
367 return NT_STATUS_FOOBAR;
370 s->schema = dsdb_get_schema(s->ldb, s);
371 if (!s->schema) {
372 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
373 return NT_STATUS_FOOBAR;
376 return NT_STATUS_OK;
379 static NTSTATUS vampire_schema_chunk(void *private_data,
380 const struct libnet_BecomeDC_StoreChunk *c)
382 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
383 WERROR status;
384 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
385 uint32_t nc_object_count;
386 uint32_t object_count;
387 struct drsuapi_DsReplicaObjectListItemEx *first_object;
388 struct drsuapi_DsReplicaObjectListItemEx *cur;
389 uint32_t nc_linked_attributes_count;
390 uint32_t linked_attributes_count;
391 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
393 switch (c->ctr_level) {
394 case 1:
395 mapping_ctr = &c->ctr1->mapping_ctr;
396 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
397 object_count = c->ctr1->object_count;
398 first_object = c->ctr1->first_object;
399 nc_linked_attributes_count = 0;
400 linked_attributes_count = 0;
401 linked_attributes = NULL;
402 break;
403 case 6:
404 mapping_ctr = &c->ctr6->mapping_ctr;
405 nc_object_count = c->ctr6->nc_object_count;
406 object_count = c->ctr6->object_count;
407 first_object = c->ctr6->first_object;
408 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
409 linked_attributes_count = c->ctr6->linked_attributes_count;
410 linked_attributes = c->ctr6->linked_attributes;
411 break;
412 default:
413 return NT_STATUS_INVALID_PARAMETER;
416 if (nc_object_count) {
417 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
418 c->partition->nc.dn, object_count, nc_object_count,
419 linked_attributes_count, nc_linked_attributes_count));
420 } else {
421 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
422 c->partition->nc.dn, object_count, linked_attributes_count));
425 if (!s->schema) {
426 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
428 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
430 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
431 if (!W_ERROR_IS_OK(status)) {
432 return werror_to_ntstatus(status);
435 s->schema = s->self_made_schema;
436 } else {
437 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->schema->prefixmap, mapping_ctr);
438 if (!W_ERROR_IS_OK(status)) {
439 return werror_to_ntstatus(status);
443 if (!s->schema_part.first_object) {
444 s->schema_part.object_count = object_count;
445 s->schema_part.first_object = talloc_steal(s, first_object);
446 } else {
447 s->schema_part.object_count += object_count;
448 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
449 first_object);
451 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
452 s->schema_part.last_object = cur;
454 if (!c->partition->more_data) {
455 return vampire_apply_schema(s, c);
458 return NT_STATUS_OK;
461 static NTSTATUS vampire_store_chunk(void *private_data,
462 const struct libnet_BecomeDC_StoreChunk *c)
464 struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
465 WERROR status;
466 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
467 uint32_t nc_object_count;
468 uint32_t object_count;
469 struct drsuapi_DsReplicaObjectListItemEx *first_object;
470 uint32_t nc_linked_attributes_count;
471 uint32_t linked_attributes_count;
472 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
473 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
474 struct dsdb_extended_replicated_objects *objs;
475 struct repsFromTo1 *s_dsa;
476 char *tmp_dns_name;
477 uint32_t i;
478 uint64_t seq_num;
480 s_dsa = talloc_zero(s, struct repsFromTo1);
481 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
482 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
483 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
485 switch (c->ctr_level) {
486 case 1:
487 mapping_ctr = &c->ctr1->mapping_ctr;
488 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
489 object_count = c->ctr1->object_count;
490 first_object = c->ctr1->first_object;
491 nc_linked_attributes_count = 0;
492 linked_attributes_count = 0;
493 linked_attributes = NULL;
494 s_dsa->highwatermark = c->ctr1->new_highwatermark;
495 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
496 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
497 uptodateness_vector = NULL; /* TODO: map it */
498 break;
499 case 6:
500 mapping_ctr = &c->ctr6->mapping_ctr;
501 nc_object_count = c->ctr6->nc_object_count;
502 object_count = c->ctr6->object_count;
503 first_object = c->ctr6->first_object;
504 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
505 linked_attributes_count = c->ctr6->linked_attributes_count;
506 linked_attributes = c->ctr6->linked_attributes;
507 s_dsa->highwatermark = c->ctr6->new_highwatermark;
508 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
509 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
510 uptodateness_vector = c->ctr6->uptodateness_vector;
511 break;
512 default:
513 return NT_STATUS_INVALID_PARAMETER;
516 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
517 | DRSUAPI_DRS_INIT_SYNC
518 | DRSUAPI_DRS_PER_SYNC;
519 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
521 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
522 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
523 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
524 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
525 s_dsa->other_info->dns_name = tmp_dns_name;
527 /* we want to show a count per partition */
528 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
529 s->total_objects = 0;
530 talloc_free(s->last_partition);
531 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
533 s->total_objects += object_count;
535 if (nc_object_count) {
536 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
537 c->partition->nc.dn, s->total_objects, nc_object_count,
538 linked_attributes_count, nc_linked_attributes_count));
539 } else {
540 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
541 c->partition->nc.dn, s->total_objects, linked_attributes_count));
545 status = dsdb_extended_replicated_objects_convert(s->ldb,
546 c->partition->nc.dn,
547 mapping_ctr,
548 object_count,
549 first_object,
550 linked_attributes_count,
551 linked_attributes,
552 s_dsa,
553 uptodateness_vector,
554 c->gensec_skey,
555 s, &objs);
556 if (!W_ERROR_IS_OK(status)) {
557 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
558 return werror_to_ntstatus(status);
561 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
562 for (i=0; i < objs->num_objects; i++) {
563 struct ldb_ldif ldif;
564 fprintf(stdout, "#\n");
565 ldif.changetype = LDB_CHANGETYPE_NONE;
566 ldif.msg = objs->objects[i].msg;
567 ldb_ldif_write_file(s->ldb, stdout, &ldif);
568 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
571 status = dsdb_extended_replicated_objects_commit(s->ldb,
572 objs, &seq_num);
573 if (!W_ERROR_IS_OK(status)) {
574 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
575 return werror_to_ntstatus(status);
578 talloc_free(s_dsa);
579 talloc_free(objs);
581 for (i=0; i < linked_attributes_count; i++) {
582 const struct dsdb_attribute *sa;
584 if (!linked_attributes[i].identifier) {
585 return NT_STATUS_FOOBAR;
588 if (!linked_attributes[i].value.blob) {
589 return NT_STATUS_FOOBAR;
592 sa = dsdb_attribute_by_attributeID_id(s->schema,
593 linked_attributes[i].attid);
594 if (!sa) {
595 return NT_STATUS_FOOBAR;
598 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
599 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
600 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
601 dump_data(0,
602 linked_attributes[i].value.blob->data,
603 linked_attributes[i].value.blob->length);
607 return NT_STATUS_OK;
610 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
611 struct libnet_Vampire *r)
613 struct libnet_JoinDomain *join;
614 struct provision_store_self_join_settings *set_secrets;
615 struct libnet_BecomeDC b;
616 struct vampire_state *s;
617 struct ldb_message *msg;
618 const char *error_string;
619 int ldb_ret;
620 uint32_t i;
621 NTSTATUS status;
623 const char *account_name;
624 const char *netbios_name;
626 r->out.error_string = NULL;
628 s = talloc_zero(mem_ctx, struct vampire_state);
629 if (!s) {
630 return NT_STATUS_NO_MEMORY;
633 s->lp_ctx = ctx->lp_ctx;
634 s->event_ctx = ctx->event_ctx;
636 join = talloc_zero(s, struct libnet_JoinDomain);
637 if (!join) {
638 return NT_STATUS_NO_MEMORY;
641 if (r->in.netbios_name != NULL) {
642 netbios_name = r->in.netbios_name;
643 } else {
644 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
645 if (!netbios_name) {
646 r->out.error_string = NULL;
647 talloc_free(s);
648 return NT_STATUS_NO_MEMORY;
652 account_name = talloc_asprintf(join, "%s$", netbios_name);
653 if (!account_name) {
654 r->out.error_string = NULL;
655 talloc_free(s);
656 return NT_STATUS_NO_MEMORY;
659 /* Re-use the domain we are joining as the domain for the user
660 * to be authenticated with, unless they specified
661 * otherwise */
662 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
664 join->in.domain_name = r->in.domain_name;
665 join->in.account_name = account_name;
666 join->in.netbios_name = netbios_name;
667 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
668 join->in.acct_type = ACB_WSTRUST;
669 join->in.recreate_account = false;
670 status = libnet_JoinDomain(ctx, join, join);
671 if (!NT_STATUS_IS_OK(status)) {
672 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
673 talloc_free(s);
674 return status;
677 s->join = join;
679 s->targetdir = r->in.targetdir;
681 ZERO_STRUCT(b);
683 /* Be more robust:
684 * We now know the domain and realm for sure - if they didn't
685 * put one on the command line, use this for the rest of the
686 * join */
687 cli_credentials_set_realm(ctx->cred, join->out.realm, CRED_GUESS_ENV);
688 cli_credentials_set_domain(ctx->cred, join->out.domain_name, CRED_GUESS_ENV);
690 /* Now set these values into the smb.conf - we probably had
691 * empty or useless defaults here from whatever smb.conf we
692 * started with */
693 lp_set_cmdline(s->lp_ctx, "realm", join->out.realm);
694 lp_set_cmdline(s->lp_ctx, "workgroup", join->out.domain_name);
696 b.in.domain_dns_name = join->out.realm;
697 b.in.domain_netbios_name = join->out.domain_name;
698 b.in.domain_sid = join->out.domain_sid;
699 b.in.source_dsa_address = join->out.samr_binding->host;
700 b.in.dest_dsa_netbios_name = netbios_name;
702 b.in.callbacks.private_data = s;
703 b.in.callbacks.check_options = vampire_check_options;
704 b.in.callbacks.prepare_db = vampire_prepare_db;
705 b.in.callbacks.schema_chunk = vampire_schema_chunk;
706 b.in.callbacks.config_chunk = vampire_store_chunk;
707 b.in.callbacks.domain_chunk = vampire_store_chunk;
709 b.in.rodc_join = lp_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
711 status = libnet_BecomeDC(ctx, s, &b);
712 if (!NT_STATUS_IS_OK(status)) {
713 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
714 talloc_free(s);
715 return status;
718 msg = ldb_msg_new(s);
719 if (!msg) {
720 printf("ldb_msg_new() failed\n");
721 talloc_free(s);
722 return NT_STATUS_NO_MEMORY;
724 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
725 if (!msg->dn) {
726 printf("ldb_msg_new(@ROOTDSE) failed\n");
727 talloc_free(s);
728 return NT_STATUS_NO_MEMORY;
731 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
732 if (ldb_ret != LDB_SUCCESS) {
733 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
734 talloc_free(s);
735 return NT_STATUS_NO_MEMORY;
738 for (i=0; i < msg->num_elements; i++) {
739 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
742 printf("mark ROOTDSE with isSynchronized=TRUE\n");
743 ldb_ret = ldb_modify(s->ldb, msg);
744 if (ldb_ret != LDB_SUCCESS) {
745 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
746 talloc_free(s);
747 return NT_STATUS_INTERNAL_DB_ERROR;
750 /* prepare the transaction - this prepares to commit all the changes in
751 the ldb from the whole vampire. Note that this
752 triggers the writing of the linked attribute backlinks.
754 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
755 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
756 return NT_STATUS_INTERNAL_DB_ERROR;
759 set_secrets = talloc(s, struct provision_store_self_join_settings);
760 if (!set_secrets) {
761 r->out.error_string = NULL;
762 talloc_free(s);
763 return NT_STATUS_NO_MEMORY;
766 ZERO_STRUCTP(set_secrets);
767 set_secrets->domain_name = join->out.domain_name;
768 set_secrets->realm = join->out.realm;
769 set_secrets->account_name = account_name;
770 set_secrets->netbios_name = netbios_name;
771 set_secrets->secure_channel_type = SEC_CHAN_BDC;
772 set_secrets->machine_password = join->out.join_password;
773 set_secrets->key_version_number = join->out.kvno;
774 set_secrets->domain_sid = join->out.domain_sid;
776 status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
777 if (!NT_STATUS_IS_OK(status)) {
778 r->out.error_string = talloc_steal(mem_ctx, error_string);
779 talloc_free(s);
780 return status;
783 r->out.domain_name = talloc_steal(mem_ctx, join->out.domain_name);
784 r->out.domain_sid = dom_sid_dup(mem_ctx, join->out.domain_sid);
786 /* commit the transaction now we know the secrets were written
787 * out properly
789 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
790 printf("Failed to commit vampire transaction\n");
791 return NT_STATUS_INTERNAL_DB_ERROR;
794 talloc_free(s);
796 return NT_STATUS_OK;