1/*
2   Unix SMB/CIFS implementation.
3
4   Extract the user/system database from a remote server
5
6   Copyright (C) Stefan Metzmacher	2004-2006
7   Copyright (C) Brad Henry 2005
8   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008
9
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.
14
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.
19
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/>.
22*/
23
24
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"
42
43/*
44List 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
54
55*/
56struct 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;
62
63	struct ldb_context *ldb;
64
65	struct {
66		uint32_t object_count;
67		struct drsuapi_DsReplicaObjectListItemEx *first_object;
68		struct drsuapi_DsReplicaObjectListItemEx *last_object;
69	} schema_part;
70
71	const char *targetdir;
72
73	struct loadparm_context *lp_ctx;
74	struct tevent_context *event_ctx;
75	unsigned total_objects;
76	char *last_partition;
77};
78
79static NTSTATUS vampire_prepare_db(void *private_data,
80					      const struct libnet_BecomeDC_PrepareDB *p)
81{
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;
86
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;
99
100	status = provision_bare(s, s->lp_ctx, &settings, &result);
101
102	if (!NT_STATUS_IS_OK(status)) {
103		return status;
104	}
105
106	s->ldb = result.samdb;
107	s->lp_ctx = result.lp_ctx;
108
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;
120	}
121
122        return NT_STATUS_OK;
123
124
125}
126
127static NTSTATUS vampire_check_options(void *private_data,
128					     const struct libnet_BecomeDC_CheckOptions *o)
129{
130	struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
131
132	DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
133		s->netbios_name,
134		o->domain->netbios_name, o->domain->dns_name));
135
136	DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
137		o->source_dsa->dns_name, o->source_dsa->site_name));
138
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));
147
148	return NT_STATUS_OK;
149}
150
151static NTSTATUS vampire_apply_schema(struct vampire_state *s,
152				  const struct libnet_BecomeDC_StoreChunk *c)
153{
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;
173
174	DEBUG(0,("Analyze and apply schema objects\n"));
175
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);
180
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;
206	}
207
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));
212
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;
218
219	for (cur = first_object; cur; cur = cur->next_object) {
220		bool is_attr = false;
221		bool is_class = false;
222
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;
227
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);
232			}
233
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;
238
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);
242					}
243
244					if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
245						is_attr = true;
246					}
247					if (val == DRSUAPI_OBJECTCLASS_classSchema) {
248						is_class = true;
249					}
250				}
251
252				break;
253			default:
254				break;
255			}
256		}
257
258		if (is_attr) {
259			struct dsdb_attribute *sa;
260
261			sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
262			NT_STATUS_HAVE_NO_MEMORY(sa);
263
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);
267			}
268
269			DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
270		}
271
272		if (is_class) {
273			struct dsdb_class *sc;
274
275			sc = talloc_zero(s->self_made_schema, struct dsdb_class);
276			NT_STATUS_HAVE_NO_MEMORY(sc);
277
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);
281			}
282
283			DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
284		}
285	}
286
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;
291	}
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);
295
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);
310	}
311
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);
320		}
321	}
322
323	msg = ldb_msg_new(objs);
324	NT_STATUS_HAVE_NO_MEMORY(msg);
325	msg->dn = objs->partition_dn;
326
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);
331	}
332
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;
337	}
338	prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
339
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;
344	}
345
346	talloc_free(s_dsa);
347	talloc_free(objs);
348
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;
355	}
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;
360	}
361
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;
366	}
367
368	return NT_STATUS_OK;
369}
370
371static NTSTATUS vampire_schema_chunk(void *private_data,
372					    const struct libnet_BecomeDC_StoreChunk *c)
373{
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;
384
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;
406	}
407
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));
415	}
416
417	if (!s->schema) {
418		s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
419
420		NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
421
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);
425		}
426
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);
432		}
433	}
434
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);
442	}
443	for (cur = first_object; cur->next_object; cur = cur->next_object) {}
444	s->schema_part.last_object = cur;
445
446	if (!c->partition->more_data) {
447		return vampire_apply_schema(s, c);
448	}
449
450	return NT_STATUS_OK;
451}
452
453static NTSTATUS vampire_store_chunk(void *private_data,
454					   const struct libnet_BecomeDC_StoreChunk *c)
455{
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;
471
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);
476
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;
506	}
507
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));
512
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;
518
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);
524	}
525	s->total_objects += object_count;
526
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));
534	}
535
536
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);
551	}
552
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);
561		}
562	}
563	talloc_free(s_dsa);
564	talloc_free(objs);
565
566	for (i=0; i < linked_attributes_count; i++) {
567		const struct dsdb_attribute *sa;
568
569		if (!linked_attributes[i].identifier) {
570			return NT_STATUS_FOOBAR;
571		}
572
573		if (!linked_attributes[i].value.blob) {
574			return NT_STATUS_FOOBAR;
575		}
576
577		sa = dsdb_attribute_by_attributeID_id(s->schema,
578						      linked_attributes[i].attid);
579		if (!sa) {
580			return NT_STATUS_FOOBAR;
581		}
582
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);
589		}
590	}
591
592	return NT_STATUS_OK;
593}
594
595NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
596			struct libnet_Vampire *r)
597{
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;
607
608	const char *account_name;
609	const char *netbios_name;
610
611	r->out.error_string = NULL;
612
613	s = talloc_zero(mem_ctx, struct vampire_state);
614	if (!s) {
615		return NT_STATUS_NO_MEMORY;
616	}
617
618	s->lp_ctx = ctx->lp_ctx;
619	s->event_ctx = ctx->event_ctx;
620
621	join = talloc_zero(s, struct libnet_JoinDomain);
622	if (!join) {
623		return NT_STATUS_NO_MEMORY;
624	}
625
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;
634		}
635	}
636
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;
642	}
643
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;
655	}
656
657	s->join = join;
658
659	s->targetdir = r->in.targetdir;
660
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;
667
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;
674
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;
680	}
681
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;
687	}
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;
693	}
694
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;
700	}
701
702	for (i=0; i < msg->num_elements; i++) {
703		msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
704	}
705
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;
712	}
713
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.
717	*/
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;
721	}
722
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;
728	}
729
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;
739
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;
745	}
746
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);
749
750	/* commit the transaction now we know the secrets were written
751	 * out properly
752	*/
753	if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
754		printf("Failed to commit vampire transaction\n");
755		return NT_STATUS_INTERNAL_DB_ERROR;
756	}
757
758	talloc_free(s);
759
760	return NT_STATUS_OK;
761
762}
763