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 <ldb.h>
31 #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 "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/security.h"
43 #include "dsdb/common/util.h"
44 
45 #undef DBGC_CLASS
46 #define DBGC_CLASS            DBGC_DRS_REPL
47 
48 /*
49 List of tasks vampire.py must perform:
50 - Domain Join
51  - but don't write the secrets.ldb
52  - results for this should be enough to handle the provision
53 - if vampire method is samsync
54  - Provision using these results
55   - do we still want to support this NT4 technology?
56 - Start samsync with libnet code
57  - provision in the callback
58 - Write out the secrets database, using the code from libnet_Join
59 
60 */
61 struct libnet_vampire_cb_state {
62 	const char *netbios_name;
63 	const char *domain_name;
64 	const char *realm;
65 	struct cli_credentials *machine_account;
66 
67 	/* Schema loaded from local LDIF files */
68 	struct dsdb_schema *provision_schema;
69 
70         /* 1st pass, with some OIDs/attribute names/class names not
71 	 * converted, because we may not know them yet */
72 	struct dsdb_schema *self_made_schema;
73 
74 	/* prefixMap in LDB format, from the remote DRS server */
75 	DATA_BLOB prefixmap_blob;
76 	const struct dsdb_schema *schema;
77 
78 	struct ldb_context *ldb;
79 
80 	struct {
81 		uint32_t object_count;
82 		struct drsuapi_DsReplicaObjectListItemEx *first_object;
83 		struct drsuapi_DsReplicaObjectListItemEx *last_object;
84 	} schema_part;
85 
86 	const char *targetdir;
87 
88 	struct loadparm_context *lp_ctx;
89 	struct tevent_context *event_ctx;
90 	unsigned total_objects;
91 	unsigned total_links;
92 	char *last_partition;
93 	const char *server_dn_str;
94 };
95 
96 /* initialise a state structure ready for replication of chunks */
libnet_vampire_replicate_init(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct loadparm_context * lp_ctx)97 void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
98 				    struct ldb_context *samdb,
99 				    struct loadparm_context *lp_ctx)
100 {
101 	struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
102 	if (!s) {
103 		return NULL;
104 	}
105 
106 	s->ldb              = samdb;
107 	s->lp_ctx           = lp_ctx;
108 	s->provision_schema = dsdb_get_schema(s->ldb, s);
109 	s->schema           = s->provision_schema;
110 	s->netbios_name     = lpcfg_netbios_name(lp_ctx);
111 	s->domain_name      = lpcfg_workgroup(lp_ctx);
112 	s->realm            = lpcfg_realm(lp_ctx);
113 
114 	return s;
115 }
116 
117 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
libnet_vampire_cb_state_init(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx,struct tevent_context * event_ctx,const char * netbios_name,const char * domain_name,const char * realm,const char * targetdir)118 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
119 				   struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
120 				   const char *netbios_name, const char *domain_name, const char *realm,
121 				   const char *targetdir)
122 {
123 	struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
124 	if (!s) {
125 		return NULL;
126 	}
127 
128 	s->lp_ctx = lp_ctx;
129 	s->event_ctx = event_ctx;
130 	s->netbios_name = netbios_name;
131 	s->domain_name = domain_name;
132 	s->realm = realm;
133 	s->targetdir = targetdir;
134 	return s;
135 }
136 
libnet_vampire_cb_ldb(struct libnet_vampire_cb_state * state)137 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
138 {
139 	state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
140 	return state->ldb;
141 }
142 
libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state * state)143 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
144 {
145 	state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
146 	return state->lp_ctx;
147 }
148 
libnet_vampire_cb_prepare_db(void * private_data,const struct libnet_BecomeDC_PrepareDB * p)149 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
150 				      const struct libnet_BecomeDC_PrepareDB *p)
151 {
152 	struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
153 	struct provision_settings settings;
154 	struct provision_result result;
155 	NTSTATUS status;
156 
157 	ZERO_STRUCT(settings);
158 	settings.site_name = p->dest_dsa->site_name;
159 	settings.root_dn_str = p->forest->root_dn_str;
160 	settings.domain_dn_str = p->domain->dn_str;
161 	settings.config_dn_str = p->forest->config_dn_str;
162 	settings.schema_dn_str = p->forest->schema_dn_str;
163 	settings.netbios_name = p->dest_dsa->netbios_name;
164 	settings.realm = s->realm;
165 	settings.domain = s->domain_name;
166 	settings.server_dn_str = p->dest_dsa->server_dn_str;
167 	settings.machine_password = generate_random_machine_password(s, 128, 255);
168 	settings.targetdir = s->targetdir;
169 	settings.use_ntvfs = true;
170 	status = provision_bare(s, s->lp_ctx, &settings, &result);
171 
172 	if (!NT_STATUS_IS_OK(status)) {
173 		return status;
174 	}
175 
176 	s->ldb = talloc_steal(s, result.samdb);
177 	s->lp_ctx = talloc_reparent(talloc_parent(result.lp_ctx), s, result.lp_ctx);
178 	s->provision_schema = dsdb_get_schema(s->ldb, s);
179 	s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
180 
181 	/* wrap the entire vapire operation in a transaction.  This
182 	   isn't just cosmetic - we use this to ensure that linked
183 	   attribute back links are added at the end by relying on a
184 	   transaction commit hook in the linked attributes module. We
185 	   need to do this as the order of objects coming from the
186 	   server is not sufficiently deterministic to know that the
187 	   record that a backlink needs to be created in has itself
188 	   been created before the object containing the forward link
189 	   has come over the wire */
190 	if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
191 		return NT_STATUS_FOOBAR;
192 	}
193 
194         return NT_STATUS_OK;
195 
196 
197 }
198 
libnet_vampire_cb_check_options(void * private_data,const struct libnet_BecomeDC_CheckOptions * o)199 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
200 					 const struct libnet_BecomeDC_CheckOptions *o)
201 {
202 	struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
203 
204 	DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
205 		s->netbios_name,
206 		o->domain->netbios_name, o->domain->dns_name));
207 
208 	DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
209 		o->source_dsa->dns_name, o->source_dsa->site_name));
210 
211 	DEBUG(0,("Options:crossRef behavior_version[%u]\n"
212 		       "\tschema object_version[%u]\n"
213 		       "\tdomain behavior_version[%u]\n"
214 		       "\tdomain w2k3_update_revision[%u]\n",
215 		o->forest->crossref_behavior_version,
216 		o->forest->schema_object_version,
217 		o->domain->behavior_version,
218 		o->domain->w2k3_update_revision));
219 
220 	return NT_STATUS_OK;
221 }
222 
libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state * s,const struct libnet_BecomeDC_StoreChunk * c)223 static WERROR libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
224 					     const struct libnet_BecomeDC_StoreChunk *c)
225 {
226 	WERROR status;
227 	struct dsdb_schema_prefixmap *pfm_remote;
228 	const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
229 	struct dsdb_schema *provision_schema;
230 	uint32_t object_count = 0;
231 	struct drsuapi_DsReplicaObjectListItemEx *first_object;
232 	uint32_t linked_attributes_count;
233 	struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
234 	const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
235 	struct dsdb_extended_replicated_objects *schema_objs;
236 	struct repsFromTo1 *s_dsa;
237 	char *tmp_dns_name;
238 	struct ldb_context *schema_ldb;
239 	struct ldb_dn *partition_dn;
240 	struct ldb_message *msg;
241 	struct ldb_message_element *prefixMap_el;
242 	uint32_t i;
243 	int ret;
244 	bool ok;
245 	uint64_t seq_num = 0;
246 	uint32_t cycle_before_switching;
247 
248 	DEBUG(0,("Analyze and apply schema objects\n"));
249 
250 	s_dsa			= talloc_zero(s, struct repsFromTo1);
251 	if (s_dsa == NULL) {
252 		return WERR_NOT_ENOUGH_MEMORY;
253 	}
254 	s_dsa->other_info	= talloc(s_dsa, struct repsFromTo1OtherInfo);
255 	if (s_dsa->other_info == NULL) {
256 		return WERR_NOT_ENOUGH_MEMORY;
257 	}
258 
259 	switch (c->ctr_level) {
260 	case 1:
261 		mapping_ctr			= &c->ctr1->mapping_ctr;
262 		object_count			= s->schema_part.object_count;
263 		first_object			= s->schema_part.first_object;
264 		linked_attributes_count		= 0;
265 		linked_attributes		= NULL;
266 		s_dsa->highwatermark		= c->ctr1->new_highwatermark;
267 		s_dsa->source_dsa_obj_guid	= c->ctr1->source_dsa_guid;
268 		s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
269 		uptodateness_vector		= NULL; /* TODO: map it */
270 		break;
271 	case 6:
272 		mapping_ctr			= &c->ctr6->mapping_ctr;
273 		object_count			= s->schema_part.object_count;
274 		first_object			= s->schema_part.first_object;
275 		linked_attributes_count		= c->ctr6->linked_attributes_count;
276 		linked_attributes		= c->ctr6->linked_attributes;
277 		s_dsa->highwatermark		= c->ctr6->new_highwatermark;
278 		s_dsa->source_dsa_obj_guid	= c->ctr6->source_dsa_guid;
279 		s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
280 		uptodateness_vector		= c->ctr6->uptodateness_vector;
281 		break;
282 	default:
283 		return WERR_INVALID_PARAMETER;
284 	}
285 	/* We must set these up to ensure the replMetaData is written
286 	 * correctly, before our NTDS Settings entry is replicated */
287 	ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
288 	if (!ok) {
289 		DEBUG(0,("Failed to set cached ntds invocationId\n"));
290 		return WERR_INTERNAL_ERROR;
291 	}
292 	ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
293 	if (!ok) {
294 		DEBUG(0,("Failed to set cached ntds objectGUID\n"));
295 		return WERR_INTERNAL_ERROR;
296 	}
297 
298 	status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
299 						  s, &pfm_remote, NULL);
300 	if (!W_ERROR_IS_OK(status)) {
301 		DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
302 			 win_errstr(status)));
303 		return status;
304 	}
305 
306 	s_dsa->replica_flags		= DRSUAPI_DRS_WRIT_REP
307 					| DRSUAPI_DRS_INIT_SYNC
308 					| DRSUAPI_DRS_PER_SYNC;
309 	memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
310 
311 	tmp_dns_name	= GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
312 	if (tmp_dns_name == NULL) {
313 		return WERR_NOT_ENOUGH_MEMORY;
314 	}
315 	tmp_dns_name	= talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
316 	if (tmp_dns_name == NULL) {
317 		return WERR_NOT_ENOUGH_MEMORY;
318 	}
319 	s_dsa->other_info->dns_name = tmp_dns_name;
320 
321 	if (s->self_made_schema == NULL) {
322 		DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
323 		return WERR_INTERNAL_ERROR;
324 	}
325 
326 	schema_ldb = provision_get_schema(s, s->lp_ctx,
327 					  c->forest->schema_dn_str,
328 					  &s->prefixmap_blob);
329 	if (!schema_ldb) {
330 		DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
331 			 "Will continue with local prefixMap\n"));
332 		provision_schema = dsdb_get_schema(s->ldb, s);
333 	} else {
334 		provision_schema = dsdb_get_schema(schema_ldb, s);
335 		ret = dsdb_reference_schema(s->ldb, provision_schema, SCHEMA_MEMORY_ONLY);
336 		if (ret != LDB_SUCCESS) {
337 			DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
338 			return WERR_INTERNAL_ERROR;
339 		}
340 		talloc_unlink(s, schema_ldb);
341 	}
342 
343 	cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
344 						 "become dc",
345 						 "schema convert retrial", 1);
346 
347 	provision_schema->resolving_in_progress = true;
348 	s->self_made_schema->resolving_in_progress = true;
349 
350 	status = dsdb_repl_resolve_working_schema(s->ldb,
351 						  pfm_remote,
352 						  cycle_before_switching,
353 						  provision_schema,
354 						  s->self_made_schema,
355 						  object_count,
356 						  first_object);
357 	if (!W_ERROR_IS_OK(status)) {
358 		DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
359 			  __location__, win_errstr(status)));
360 		return status;
361 	}
362 
363 	/* free temp objects for 1st conversion phase */
364 	talloc_unlink(s, provision_schema);
365 
366 	s->self_made_schema->resolving_in_progress = false;
367 
368 	/*
369 	 * attach the schema we just brought over DRS to the ldb,
370 	 * so we can use it in dsdb_convert_object_ex below
371 	 */
372 	ret = dsdb_set_schema(s->ldb, s->self_made_schema, SCHEMA_WRITE);
373 	if (ret != LDB_SUCCESS) {
374 		DEBUG(0,("Failed to attach working schema from DRS.\n"));
375 		return WERR_INTERNAL_ERROR;
376 	}
377 
378 	/* we don't want to access the self made schema anymore */
379 	s->schema = s->self_made_schema;
380 	s->self_made_schema = NULL;
381 
382 	partition_dn = ldb_dn_new(s, s->ldb, c->partition->nc.dn);
383 	if (partition_dn == NULL) {
384 		DEBUG(0,("Failed to parse partition DN from DRS.\n"));
385 		return WERR_INVALID_PARAMETER;
386 	}
387 
388 	/* Now convert the schema elements again, using the schema we finalised, ready to actually import */
389 	status = dsdb_replicated_objects_convert(s->ldb,
390 						 s->schema,
391 						 partition_dn,
392 						 mapping_ctr,
393 						 object_count,
394 						 first_object,
395 						 linked_attributes_count,
396 						 linked_attributes,
397 						 s_dsa,
398 						 uptodateness_vector,
399 						 c->gensec_skey,
400 						 0,
401 						 s, &schema_objs);
402 	if (!W_ERROR_IS_OK(status)) {
403 		DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
404 		return status;
405 	}
406 
407 	if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
408 		for (i=0; i < schema_objs->num_objects; i++) {
409 			struct ldb_ldif ldif;
410 			fprintf(stdout, "#\n");
411 			ldif.changetype = LDB_CHANGETYPE_NONE;
412 			ldif.msg = schema_objs->objects[i].msg;
413 			ldb_ldif_write_file(s->ldb, stdout, &ldif);
414 			NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
415 		}
416 	}
417 
418 	status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
419 	if (!W_ERROR_IS_OK(status)) {
420 		DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
421 		return status;
422 	}
423 
424 	msg = ldb_msg_new(schema_objs);
425 	if (msg == NULL) {
426 		return WERR_NOT_ENOUGH_MEMORY;
427 	}
428 	msg->dn = schema_objs->partition_dn;
429 
430 	/* We must ensure a prefixMap has been written.  Unlike other
431 	 * attributes (including schemaInfo), it is not replicated in
432 	 * the normal replication stream.  We can use the one from
433 	 * s->prefixmap_blob because we operate with one, unchanging
434 	 * prefixMap for this entire operation.  */
435 	ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
436 	if (ret != LDB_SUCCESS) {
437 		return WERR_NOT_ENOUGH_MEMORY;
438 	}
439 	/* We want to know if a prefixMap was written already, as it
440 	 * would mean that the above comment was not true, and we have
441 	 * somehow updated the prefixMap during this transaction */
442 	prefixMap_el->flags = LDB_FLAG_MOD_ADD;
443 
444 	ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
445 	if (ret != LDB_SUCCESS) {
446 		DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
447 		return WERR_INTERNAL_ERROR;
448 	}
449 
450 	talloc_free(s_dsa);
451 	talloc_free(schema_objs);
452 
453 	s->schema = dsdb_get_schema(s->ldb, s);
454 	if (!s->schema) {
455 		DEBUG(0,("Failed to get loaded dsdb_schema\n"));
456 		return WERR_INTERNAL_ERROR;
457 	}
458 
459 	return WERR_OK;
460 }
461 
libnet_vampire_cb_schema_chunk(void * private_data,const struct libnet_BecomeDC_StoreChunk * c)462 WERROR libnet_vampire_cb_schema_chunk(void *private_data,
463 				      const struct libnet_BecomeDC_StoreChunk *c)
464 {
465 	struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
466 	WERROR werr;
467 	const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
468 	uint32_t nc_object_count;
469 	uint32_t nc_total_received = 0;
470 	uint32_t object_count;
471 	struct drsuapi_DsReplicaObjectListItemEx *first_object;
472 	struct drsuapi_DsReplicaObjectListItemEx *cur;
473 	uint32_t nc_linked_attributes_count;
474 	uint32_t linked_attributes_count;
475 
476 	switch (c->ctr_level) {
477 	case 1:
478 		mapping_ctr			= &c->ctr1->mapping_ctr;
479 		nc_object_count			= c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
480 		object_count			= c->ctr1->object_count;
481 		first_object			= c->ctr1->first_object;
482 		nc_linked_attributes_count	= 0;
483 		linked_attributes_count		= 0;
484 		break;
485 	case 6:
486 		mapping_ctr			= &c->ctr6->mapping_ctr;
487 		nc_object_count			= c->ctr6->nc_object_count;
488 		object_count			= c->ctr6->object_count;
489 		first_object			= c->ctr6->first_object;
490 		nc_linked_attributes_count	= c->ctr6->nc_linked_attributes_count;
491 		linked_attributes_count		= c->ctr6->linked_attributes_count;
492 		break;
493 	default:
494 		return WERR_INVALID_PARAMETER;
495 	}
496 
497 	if (!s->schema_part.first_object) {
498 		nc_total_received = object_count;
499 	} else {
500 		nc_total_received = s->schema_part.object_count + object_count;
501 	}
502 	if (nc_object_count) {
503 		DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
504 			c->partition->nc.dn, nc_total_received, nc_object_count,
505 			linked_attributes_count, nc_linked_attributes_count));
506 	} else {
507 		DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
508 		c->partition->nc.dn, nc_total_received, linked_attributes_count));
509 	}
510 
511 	if (!s->self_made_schema) {
512 		struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
513 		/* Put the DRS prefixmap aside for the schema we are
514 		 * about to load in the provision, and into the one we
515 		 * are making with the help of DRS */
516 
517 		mapping_ctr_without_schema_info = *mapping_ctr;
518 
519 		/* This strips off the 0xFF schema info from the end,
520 		 * because we don't want it in the blob */
521 		if (mapping_ctr_without_schema_info.num_mappings > 0) {
522 			mapping_ctr_without_schema_info.num_mappings--;
523 		}
524 		werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
525 		if (!W_ERROR_IS_OK(werr)) {
526 			return werr;
527 		}
528 
529 		/* Set up two manually-constructed schema - the local
530 		 * schema from the provision will be used to build
531 		 * one, which will then in turn be used to build the
532 		 * other. */
533 		s->self_made_schema = dsdb_new_schema(s);
534 		if (s->self_made_schema == NULL) {
535 			return WERR_NOT_ENOUGH_MEMORY;
536 		}
537 
538 		werr = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
539 		if (!W_ERROR_IS_OK(werr)) {
540 			return werr;
541 		}
542 	} else {
543 		werr = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
544 		if (!W_ERROR_IS_OK(werr)) {
545 			return werr;
546 		}
547 	}
548 
549 	if (!s->schema_part.first_object) {
550 		s->schema_part.object_count = object_count;
551 		s->schema_part.first_object = talloc_steal(s, first_object);
552 	} else {
553 		s->schema_part.object_count		+= object_count;
554 		s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
555 								       first_object);
556 	}
557 	if (first_object != NULL) {
558 		for (cur = first_object; cur->next_object; cur = cur->next_object) {}
559 	} else {
560 		cur = first_object;
561 	}
562 
563 	s->schema_part.last_object = cur;
564 
565 	if (!c->partition->more_data) {
566 		return libnet_vampire_cb_apply_schema(s, c);
567 	}
568 
569 	return WERR_OK;
570 }
571 
libnet_vampire_cb_store_chunk(void * private_data,const struct libnet_BecomeDC_StoreChunk * c)572 WERROR libnet_vampire_cb_store_chunk(void *private_data,
573 				     const struct libnet_BecomeDC_StoreChunk *c)
574 {
575 	struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
576 	WERROR status;
577 	struct dsdb_schema *schema;
578 	const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
579 	uint32_t nc_object_count;
580 	uint32_t object_count;
581 	struct drsuapi_DsReplicaObjectListItemEx *first_object;
582 	uint32_t nc_linked_attributes_count;
583 	uint32_t linked_attributes_count;
584 	struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
585 	const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
586 	struct dsdb_extended_replicated_objects *objs;
587 	uint32_t req_replica_flags;
588 	uint32_t dsdb_repl_flags = 0;
589 	struct repsFromTo1 *s_dsa;
590 	char *tmp_dns_name;
591 	uint32_t i;
592 	uint64_t seq_num;
593 	bool is_exop = false;
594 	struct ldb_dn *partition_dn = NULL;
595 	struct ldb_dn *nc_root = NULL;
596 
597 	s_dsa			= talloc_zero(s, struct repsFromTo1);
598 	if (s_dsa == NULL) {
599 		return WERR_NOT_ENOUGH_MEMORY;
600 	}
601 	s_dsa->other_info	= talloc(s_dsa, struct repsFromTo1OtherInfo);
602 	if (s_dsa->other_info == NULL) {
603 		return WERR_NOT_ENOUGH_MEMORY;
604 	}
605 
606 	switch (c->ctr_level) {
607 	case 1:
608 		mapping_ctr			= &c->ctr1->mapping_ctr;
609 		nc_object_count			= c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
610 		object_count			= c->ctr1->object_count;
611 		first_object			= c->ctr1->first_object;
612 		nc_linked_attributes_count	= 0;
613 		linked_attributes_count		= 0;
614 		linked_attributes		= NULL;
615 		s_dsa->highwatermark		= c->ctr1->new_highwatermark;
616 		s_dsa->source_dsa_obj_guid	= c->ctr1->source_dsa_guid;
617 		s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
618 		uptodateness_vector		= NULL; /* TODO: map it */
619 		break;
620 	case 6:
621 		mapping_ctr			= &c->ctr6->mapping_ctr;
622 		nc_object_count			= c->ctr6->nc_object_count;
623 		object_count			= c->ctr6->object_count;
624 		first_object			= c->ctr6->first_object;
625 		nc_linked_attributes_count	= c->ctr6->nc_linked_attributes_count;
626 		linked_attributes_count		= c->ctr6->linked_attributes_count;
627 		linked_attributes		= c->ctr6->linked_attributes;
628 		s_dsa->highwatermark		= c->ctr6->new_highwatermark;
629 		s_dsa->source_dsa_obj_guid	= c->ctr6->source_dsa_guid;
630 		s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
631 		uptodateness_vector		= c->ctr6->uptodateness_vector;
632 		break;
633 	default:
634 		return WERR_INVALID_PARAMETER;
635 	}
636 
637 	switch (c->req_level) {
638 	case 0:
639 		/* none */
640 		req_replica_flags = 0;
641 		break;
642 	case 5:
643 		if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
644 			is_exop = true;
645 		}
646 		req_replica_flags = c->req5->replica_flags;
647 		break;
648 	case 8:
649 		if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
650 			is_exop = true;
651 		}
652 		req_replica_flags = c->req8->replica_flags;
653 		break;
654 	case 10:
655 		if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
656 			is_exop = true;
657 		}
658 		req_replica_flags = c->req10->replica_flags;
659 
660 		if (c->req10->more_flags & DRSUAPI_DRS_GET_TGT) {
661 			dsdb_repl_flags |= DSDB_REPL_FLAG_TARGETS_UPTODATE;
662 		}
663 		break;
664 	default:
665 		return WERR_INVALID_PARAMETER;
666 	}
667 
668 	/*
669 	 * If the peer DC doesn't support GET_TGT (req v10), then the link
670 	 * targets are as up-to-date as they're ever gonna be. (Without this,
671 	 * cases where we'd normally retry with GET_TGT cause the join to fail)
672 	 */
673 	if (c->req_level < 10) {
674 		dsdb_repl_flags |= DSDB_REPL_FLAG_TARGETS_UPTODATE;
675 	}
676 
677 	if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY || is_exop) {
678 		/*
679 		 * If we only replicate the critical objects, or this
680 		 * is an exop we should not remember what we already
681 		 * got, as it is incomplete.
682 		 */
683 		ZERO_STRUCT(s_dsa->highwatermark);
684 		uptodateness_vector = NULL;
685 		dsdb_repl_flags |= DSDB_REPL_FLAG_OBJECT_SUBSET;
686 	}
687 
688 	/* TODO: avoid hardcoded flags */
689 	s_dsa->replica_flags		= DRSUAPI_DRS_WRIT_REP
690 					| DRSUAPI_DRS_INIT_SYNC
691 					| DRSUAPI_DRS_PER_SYNC;
692 	memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
693 
694 	tmp_dns_name	= GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
695 	if (tmp_dns_name == NULL) {
696 		return WERR_NOT_ENOUGH_MEMORY;
697 	}
698 	tmp_dns_name	= talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
699 	if (tmp_dns_name == NULL) {
700 		return WERR_NOT_ENOUGH_MEMORY;
701 	}
702 	s_dsa->other_info->dns_name = tmp_dns_name;
703 
704 	/* we want to show a count per partition */
705 	if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
706 		s->total_objects = 0;
707 		s->total_links = 0;
708 		talloc_free(s->last_partition);
709 		s->last_partition = talloc_strdup(s, c->partition->nc.dn);
710 	}
711 	s->total_objects += object_count;
712 	s->total_links += linked_attributes_count;
713 
714 	partition_dn = ldb_dn_new(s_dsa, s->ldb, c->partition->nc.dn);
715 	if (partition_dn == NULL) {
716 		DEBUG(0,("Failed to parse partition DN from DRS.\n"));
717 		return WERR_INVALID_PARAMETER;
718 	}
719 
720 	if (is_exop) {
721 		int ret;
722 		if (nc_object_count) {
723 			DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
724 				c->partition->nc.dn, s->total_objects, nc_object_count,
725 				s->total_links, nc_linked_attributes_count));
726 		} else {
727 			DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
728 			c->partition->nc.dn, s->total_objects, linked_attributes_count));
729 		}
730 		ret = dsdb_find_nc_root(s->ldb, s_dsa,
731 					partition_dn, &nc_root);
732 		if (ret != LDB_SUCCESS) {
733 			DEBUG(0,(__location__ ": Failed to find nc_root for %s\n",
734 				 ldb_dn_get_linearized(partition_dn)));
735 			return WERR_INTERNAL_ERROR;
736 		}
737 	} else {
738 		if (nc_object_count) {
739 			DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
740 				c->partition->nc.dn, s->total_objects, nc_object_count,
741 				s->total_links, nc_linked_attributes_count));
742 		} else {
743 			DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
744 			c->partition->nc.dn, s->total_objects, s->total_links));
745 		}
746 		nc_root = partition_dn;
747 	}
748 
749 
750 	schema = dsdb_get_schema(s->ldb, NULL);
751 	if (!schema) {
752 		DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
753 		return WERR_INTERNAL_ERROR;
754 	}
755 
756 	if (req_replica_flags & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS) {
757 		dsdb_repl_flags |= DSDB_REPL_FLAG_PRIORITISE_INCOMING;
758 	}
759 
760 	if (req_replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
761 		dsdb_repl_flags |= DSDB_REPL_FLAG_EXPECT_NO_SECRETS;
762 	}
763 
764 	status = dsdb_replicated_objects_convert(s->ldb,
765 						 schema,
766 						 nc_root,
767 						 mapping_ctr,
768 						 object_count,
769 						 first_object,
770 						 linked_attributes_count,
771 						 linked_attributes,
772 						 s_dsa,
773 						 uptodateness_vector,
774 						 c->gensec_skey,
775 						 dsdb_repl_flags,
776 						 s, &objs);
777 	if (!W_ERROR_IS_OK(status)) {
778 		DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
779 		return status;
780 	}
781 
782 	if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
783 		for (i=0; i < objs->num_objects; i++) {
784 			struct ldb_ldif ldif;
785 			fprintf(stdout, "#\n");
786 			ldif.changetype = LDB_CHANGETYPE_NONE;
787 			ldif.msg = objs->objects[i].msg;
788 			ldb_ldif_write_file(s->ldb, stdout, &ldif);
789 			NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
790 		}
791 	}
792 	status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
793 	if (!W_ERROR_IS_OK(status)) {
794 		DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
795 		return status;
796 	}
797 
798 	/* reset debug counters once we've finished replicating the partition */
799 	if (!c->partition->more_data) {
800 		s->total_objects = 0;
801 		s->total_links = 0;
802 	}
803 
804 	talloc_free(s_dsa);
805 	talloc_free(objs);
806 
807 	for (i=0; i < linked_attributes_count; i++) {
808 		const struct dsdb_attribute *sa;
809 
810 		if (!linked_attributes[i].identifier) {
811 			DEBUG(0, ("No linked attribute identifier\n"));
812 			return WERR_INTERNAL_ERROR;
813 		}
814 
815 		if (!linked_attributes[i].value.blob) {
816 			DEBUG(0, ("No linked attribute value\n"));
817 			return WERR_INTERNAL_ERROR;
818 		}
819 
820 		sa = dsdb_attribute_by_attributeID_id(s->schema,
821 						      linked_attributes[i].attid);
822 		if (!sa) {
823 			DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes[i].attid));
824 			return WERR_INTERNAL_ERROR;
825 		}
826 
827 		if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
828 			DEBUG(0,("# %s\n", sa->lDAPDisplayName));
829 			NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
830 			dump_data(0,
831 				linked_attributes[i].value.blob->data,
832 				linked_attributes[i].value.blob->length);
833 		}
834 	}
835 
836 	return WERR_OK;
837 }
838 
839