bugfix memory leak. partition_dn is only used to search and compare and is not freed...
[Samba.git] / source4 / libnet / libnet_vampire.c
blobc4ef60863312240ed11ab6b612b27baa42d74476
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 <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"
45 #undef DBGC_CLASS
46 #define DBGC_CLASS DBGC_DRS_REPL
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
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;
67 /* Schema loaded from local LDIF files */
68 struct dsdb_schema *provision_schema;
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;
74 /* prefixMap in LDB format, from the remote DRS server */
75 DATA_BLOB prefixmap_blob;
76 const struct dsdb_schema *schema;
78 struct ldb_context *ldb;
80 struct {
81 uint32_t object_count;
82 struct drsuapi_DsReplicaObjectListItemEx *first_object;
83 struct drsuapi_DsReplicaObjectListItemEx *last_object;
84 } schema_part;
86 const char *targetdir;
88 struct loadparm_context *lp_ctx;
89 struct tevent_context *event_ctx;
90 unsigned total_objects;
91 char *last_partition;
92 const char *server_dn_str;
95 /* initialise a state structure ready for replication of chunks */
96 void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
97 struct ldb_context *samdb,
98 struct loadparm_context *lp_ctx)
100 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
101 if (!s) {
102 return NULL;
105 s->ldb = samdb;
106 s->lp_ctx = lp_ctx;
107 s->provision_schema = dsdb_get_schema(s->ldb, s);
108 s->schema = s->provision_schema;
109 s->netbios_name = lpcfg_netbios_name(lp_ctx);
110 s->domain_name = lpcfg_workgroup(lp_ctx);
111 s->realm = lpcfg_realm(lp_ctx);
113 return s;
116 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
117 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
118 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
119 const char *netbios_name, const char *domain_name, const char *realm,
120 const char *targetdir)
122 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
123 if (!s) {
124 return NULL;
127 s->lp_ctx = lp_ctx;
128 s->event_ctx = event_ctx;
129 s->netbios_name = netbios_name;
130 s->domain_name = domain_name;
131 s->realm = realm;
132 s->targetdir = targetdir;
133 return s;
136 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
138 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
139 return state->ldb;
142 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
144 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
145 return state->lp_ctx;
148 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
149 const struct libnet_BecomeDC_PrepareDB *p)
151 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
152 struct provision_settings settings;
153 struct provision_result result;
154 NTSTATUS status;
156 ZERO_STRUCT(settings);
157 settings.site_name = p->dest_dsa->site_name;
158 settings.root_dn_str = p->forest->root_dn_str;
159 settings.domain_dn_str = p->domain->dn_str;
160 settings.config_dn_str = p->forest->config_dn_str;
161 settings.schema_dn_str = p->forest->schema_dn_str;
162 settings.netbios_name = p->dest_dsa->netbios_name;
163 settings.realm = s->realm;
164 settings.domain = s->domain_name;
165 settings.server_dn_str = p->dest_dsa->server_dn_str;
166 settings.machine_password = generate_random_machine_password(s, 128, 255);
167 settings.targetdir = s->targetdir;
168 settings.use_ntvfs = true;
169 status = provision_bare(s, s->lp_ctx, &settings, &result);
171 if (!NT_STATUS_IS_OK(status)) {
172 return status;
175 s->ldb = talloc_steal(s, result.samdb);
176 s->lp_ctx = talloc_reparent(talloc_parent(result.lp_ctx), s, result.lp_ctx);
177 s->provision_schema = dsdb_get_schema(s->ldb, s);
178 s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
180 /* wrap the entire vapire operation in a transaction. This
181 isn't just cosmetic - we use this to ensure that linked
182 attribute back links are added at the end by relying on a
183 transaction commit hook in the linked attributes module. We
184 need to do this as the order of objects coming from the
185 server is not sufficiently deterministic to know that the
186 record that a backlink needs to be created in has itself
187 been created before the object containing the forward link
188 has come over the wire */
189 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
190 return NT_STATUS_FOOBAR;
193 return NT_STATUS_OK;
198 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
199 const struct libnet_BecomeDC_CheckOptions *o)
201 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
203 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
204 s->netbios_name,
205 o->domain->netbios_name, o->domain->dns_name));
207 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
208 o->source_dsa->dns_name, o->source_dsa->site_name));
210 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
211 "\tschema object_version[%u]\n"
212 "\tdomain behavior_version[%u]\n"
213 "\tdomain w2k3_update_revision[%u]\n",
214 o->forest->crossref_behavior_version,
215 o->forest->schema_object_version,
216 o->domain->behavior_version,
217 o->domain->w2k3_update_revision));
219 return NT_STATUS_OK;
222 static WERROR libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
223 const struct libnet_BecomeDC_StoreChunk *c)
225 WERROR status;
226 struct dsdb_schema_prefixmap *pfm_remote;
227 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
228 struct dsdb_schema *provision_schema;
229 uint32_t object_count = 0;
230 struct drsuapi_DsReplicaObjectListItemEx *first_object;
231 uint32_t linked_attributes_count;
232 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
233 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
234 struct dsdb_extended_replicated_objects *schema_objs;
235 struct repsFromTo1 *s_dsa;
236 char *tmp_dns_name;
237 struct ldb_context *schema_ldb;
238 struct ldb_dn *partition_dn;
239 struct ldb_message *msg;
240 struct ldb_message_element *prefixMap_el;
241 uint32_t i;
242 int ret;
243 bool ok;
244 uint64_t seq_num = 0;
245 uint32_t cycle_before_switching;
247 DEBUG(0,("Analyze and apply schema objects\n"));
249 s_dsa = talloc_zero(s, struct repsFromTo1);
250 if (s_dsa == NULL) {
251 return WERR_NOT_ENOUGH_MEMORY;
253 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
254 if (s_dsa->other_info == NULL) {
255 return WERR_NOT_ENOUGH_MEMORY;
258 switch (c->ctr_level) {
259 case 1:
260 mapping_ctr = &c->ctr1->mapping_ctr;
261 object_count = s->schema_part.object_count;
262 first_object = s->schema_part.first_object;
263 linked_attributes_count = 0;
264 linked_attributes = NULL;
265 s_dsa->highwatermark = c->ctr1->new_highwatermark;
266 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
267 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
268 uptodateness_vector = NULL; /* TODO: map it */
269 break;
270 case 6:
271 mapping_ctr = &c->ctr6->mapping_ctr;
272 object_count = s->schema_part.object_count;
273 first_object = s->schema_part.first_object;
274 linked_attributes_count = c->ctr6->linked_attributes_count;
275 linked_attributes = c->ctr6->linked_attributes;
276 s_dsa->highwatermark = c->ctr6->new_highwatermark;
277 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
278 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
279 uptodateness_vector = c->ctr6->uptodateness_vector;
280 break;
281 default:
282 return WERR_INVALID_PARAMETER;
284 /* We must set these up to ensure the replMetaData is written
285 * correctly, before our NTDS Settings entry is replicated */
286 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
287 if (!ok) {
288 DEBUG(0,("Failed to set cached ntds invocationId\n"));
289 return WERR_INTERNAL_ERROR;
291 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
292 if (!ok) {
293 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
294 return WERR_INTERNAL_ERROR;
297 status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
298 s, &pfm_remote, NULL);
299 if (!W_ERROR_IS_OK(status)) {
300 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
301 win_errstr(status)));
302 return status;
305 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
306 | DRSUAPI_DRS_INIT_SYNC
307 | DRSUAPI_DRS_PER_SYNC;
308 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
310 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
311 if (tmp_dns_name == NULL) {
312 return WERR_NOT_ENOUGH_MEMORY;
314 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
315 if (tmp_dns_name == NULL) {
316 return WERR_NOT_ENOUGH_MEMORY;
318 s_dsa->other_info->dns_name = tmp_dns_name;
320 if (s->self_made_schema == NULL) {
321 DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
322 return WERR_INTERNAL_ERROR;
325 schema_ldb = provision_get_schema(s, s->lp_ctx,
326 c->forest->schema_dn_str,
327 &s->prefixmap_blob);
328 if (!schema_ldb) {
329 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
330 "Will continue with local prefixMap\n"));
331 provision_schema = dsdb_get_schema(s->ldb, s);
332 } else {
333 provision_schema = dsdb_get_schema(schema_ldb, s);
334 ret = dsdb_reference_schema(s->ldb, provision_schema, SCHEMA_MEMORY_ONLY);
335 if (ret != LDB_SUCCESS) {
336 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
337 return WERR_INTERNAL_ERROR;
339 talloc_free(schema_ldb);
342 cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
343 "become dc",
344 "schema convert retrial", 1);
346 provision_schema->resolving_in_progress = true;
347 s->self_made_schema->resolving_in_progress = true;
349 status = dsdb_repl_resolve_working_schema(s->ldb,
350 pfm_remote,
351 cycle_before_switching,
352 provision_schema,
353 s->self_made_schema,
354 object_count,
355 first_object);
356 if (!W_ERROR_IS_OK(status)) {
357 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
358 __location__, win_errstr(status)));
359 return status;
362 /* free temp objects for 1st conversion phase */
363 talloc_unlink(s, provision_schema);
365 s->self_made_schema->resolving_in_progress = false;
368 * attach the schema we just brought over DRS to the ldb,
369 * so we can use it in dsdb_convert_object_ex below
371 ret = dsdb_set_schema(s->ldb, s->self_made_schema, SCHEMA_WRITE);
372 if (ret != LDB_SUCCESS) {
373 DEBUG(0,("Failed to attach working schema from DRS.\n"));
374 return WERR_INTERNAL_ERROR;
377 /* we don't want to access the self made schema anymore */
378 s->schema = s->self_made_schema;
379 s->self_made_schema = NULL;
381 partition_dn = ldb_dn_new(s, s->ldb, c->partition->nc.dn);
382 if (partition_dn == NULL) {
383 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
384 return WERR_INVALID_PARAMETER;
387 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
388 status = dsdb_replicated_objects_convert(s->ldb,
389 s->schema,
390 partition_dn,
391 mapping_ctr,
392 object_count,
393 first_object,
394 linked_attributes_count,
395 linked_attributes,
396 s_dsa,
397 uptodateness_vector,
398 c->gensec_skey,
400 s, &schema_objs);
401 if (!W_ERROR_IS_OK(status)) {
402 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
403 return status;
406 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
407 for (i=0; i < schema_objs->num_objects; i++) {
408 struct ldb_ldif ldif;
409 fprintf(stdout, "#\n");
410 ldif.changetype = LDB_CHANGETYPE_NONE;
411 ldif.msg = schema_objs->objects[i].msg;
412 ldb_ldif_write_file(s->ldb, stdout, &ldif);
413 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
417 status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
418 if (!W_ERROR_IS_OK(status)) {
419 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
420 return status;
423 msg = ldb_msg_new(schema_objs);
424 if (msg == NULL) {
425 return WERR_NOT_ENOUGH_MEMORY;
427 msg->dn = schema_objs->partition_dn;
429 /* We must ensure a prefixMap has been written. Unlike other
430 * attributes (including schemaInfo), it is not replicated in
431 * the normal replication stream. We can use the one from
432 * s->prefixmap_blob because we operate with one, unchanging
433 * prefixMap for this entire operation. */
434 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
435 if (ret != LDB_SUCCESS) {
436 return WERR_NOT_ENOUGH_MEMORY;
438 /* We want to know if a prefixMap was written already, as it
439 * would mean that the above comment was not true, and we have
440 * somehow updated the prefixMap during this transaction */
441 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
443 ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
444 if (ret != LDB_SUCCESS) {
445 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
446 return WERR_INTERNAL_ERROR;
449 talloc_free(s_dsa);
450 talloc_free(schema_objs);
452 s->schema = dsdb_get_schema(s->ldb, s);
453 if (!s->schema) {
454 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
455 return WERR_INTERNAL_ERROR;
458 return WERR_OK;
461 WERROR libnet_vampire_cb_schema_chunk(void *private_data,
462 const struct libnet_BecomeDC_StoreChunk *c)
464 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
465 WERROR werr;
466 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
467 uint32_t nc_object_count;
468 uint32_t nc_total_received = 0;
469 uint32_t object_count;
470 struct drsuapi_DsReplicaObjectListItemEx *first_object;
471 struct drsuapi_DsReplicaObjectListItemEx *cur;
472 uint32_t nc_linked_attributes_count;
473 uint32_t linked_attributes_count;
475 switch (c->ctr_level) {
476 case 1:
477 mapping_ctr = &c->ctr1->mapping_ctr;
478 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
479 object_count = c->ctr1->object_count;
480 first_object = c->ctr1->first_object;
481 nc_linked_attributes_count = 0;
482 linked_attributes_count = 0;
483 break;
484 case 6:
485 mapping_ctr = &c->ctr6->mapping_ctr;
486 nc_object_count = c->ctr6->nc_object_count;
487 object_count = c->ctr6->object_count;
488 first_object = c->ctr6->first_object;
489 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
490 linked_attributes_count = c->ctr6->linked_attributes_count;
491 break;
492 default:
493 return WERR_INVALID_PARAMETER;
496 if (!s->schema_part.first_object) {
497 nc_total_received = object_count;
498 } else {
499 nc_total_received = s->schema_part.object_count + object_count;
501 if (nc_object_count) {
502 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
503 c->partition->nc.dn, nc_total_received, nc_object_count,
504 linked_attributes_count, nc_linked_attributes_count));
505 } else {
506 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
507 c->partition->nc.dn, nc_total_received, linked_attributes_count));
510 if (!s->self_made_schema) {
511 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
512 /* Put the DRS prefixmap aside for the schema we are
513 * about to load in the provision, and into the one we
514 * are making with the help of DRS */
516 mapping_ctr_without_schema_info = *mapping_ctr;
518 /* This strips off the 0xFF schema info from the end,
519 * because we don't want it in the blob */
520 if (mapping_ctr_without_schema_info.num_mappings > 0) {
521 mapping_ctr_without_schema_info.num_mappings--;
523 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
524 if (!W_ERROR_IS_OK(werr)) {
525 return werr;
528 /* Set up two manually-constructed schema - the local
529 * schema from the provision will be used to build
530 * one, which will then in turn be used to build the
531 * other. */
532 s->self_made_schema = dsdb_new_schema(s);
533 if (s->self_made_schema == NULL) {
534 return WERR_NOT_ENOUGH_MEMORY;
537 werr = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
538 if (!W_ERROR_IS_OK(werr)) {
539 return werr;
541 } else {
542 werr = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
543 if (!W_ERROR_IS_OK(werr)) {
544 return werr;
548 if (!s->schema_part.first_object) {
549 s->schema_part.object_count = object_count;
550 s->schema_part.first_object = talloc_steal(s, first_object);
551 } else {
552 s->schema_part.object_count += object_count;
553 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
554 first_object);
556 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
557 s->schema_part.last_object = cur;
559 if (!c->partition->more_data) {
560 return libnet_vampire_cb_apply_schema(s, c);
563 return WERR_OK;
566 WERROR libnet_vampire_cb_store_chunk(void *private_data,
567 const struct libnet_BecomeDC_StoreChunk *c)
569 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
570 WERROR status;
571 struct dsdb_schema *schema;
572 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
573 uint32_t nc_object_count;
574 uint32_t object_count;
575 struct drsuapi_DsReplicaObjectListItemEx *first_object;
576 uint32_t nc_linked_attributes_count;
577 uint32_t linked_attributes_count;
578 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
579 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
580 struct dsdb_extended_replicated_objects *objs;
581 uint32_t req_replica_flags;
582 uint32_t dsdb_repl_flags = 0;
583 struct repsFromTo1 *s_dsa;
584 char *tmp_dns_name;
585 uint32_t i;
586 uint64_t seq_num;
587 bool is_exop = false;
588 struct ldb_dn *partition_dn = NULL;
589 struct ldb_dn *nc_root = NULL;
591 s_dsa = talloc_zero(s, struct repsFromTo1);
592 if (s_dsa == NULL) {
593 return WERR_NOT_ENOUGH_MEMORY;
595 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
596 if (s_dsa->other_info == NULL) {
597 return WERR_NOT_ENOUGH_MEMORY;
600 switch (c->ctr_level) {
601 case 1:
602 mapping_ctr = &c->ctr1->mapping_ctr;
603 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
604 object_count = c->ctr1->object_count;
605 first_object = c->ctr1->first_object;
606 nc_linked_attributes_count = 0;
607 linked_attributes_count = 0;
608 linked_attributes = NULL;
609 s_dsa->highwatermark = c->ctr1->new_highwatermark;
610 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
611 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
612 uptodateness_vector = NULL; /* TODO: map it */
613 break;
614 case 6:
615 mapping_ctr = &c->ctr6->mapping_ctr;
616 nc_object_count = c->ctr6->nc_object_count;
617 object_count = c->ctr6->object_count;
618 first_object = c->ctr6->first_object;
619 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
620 linked_attributes_count = c->ctr6->linked_attributes_count;
621 linked_attributes = c->ctr6->linked_attributes;
622 s_dsa->highwatermark = c->ctr6->new_highwatermark;
623 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
624 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
625 uptodateness_vector = c->ctr6->uptodateness_vector;
626 break;
627 default:
628 return WERR_INVALID_PARAMETER;
631 switch (c->req_level) {
632 case 0:
633 /* none */
634 req_replica_flags = 0;
635 break;
636 case 5:
637 if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
638 is_exop = true;
640 req_replica_flags = c->req5->replica_flags;
641 break;
642 case 8:
643 if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
644 is_exop = true;
646 req_replica_flags = c->req8->replica_flags;
647 break;
648 case 10:
649 if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
650 is_exop = true;
652 req_replica_flags = c->req10->replica_flags;
654 if (c->req10->more_flags & DRSUAPI_DRS_GET_TGT) {
655 dsdb_repl_flags |= DSDB_REPL_FLAG_TARGETS_UPTODATE;
657 break;
658 default:
659 return WERR_INVALID_PARAMETER;
662 if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY || is_exop) {
664 * If we only replicate the critical objects, or this
665 * is an exop we should not remember what we already
666 * got, as it is incomplete.
668 ZERO_STRUCT(s_dsa->highwatermark);
669 uptodateness_vector = NULL;
670 dsdb_repl_flags |= DSDB_REPL_FLAG_OBJECT_SUBSET;
673 /* TODO: avoid hardcoded flags */
674 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
675 | DRSUAPI_DRS_INIT_SYNC
676 | DRSUAPI_DRS_PER_SYNC;
677 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
679 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
680 if (tmp_dns_name == NULL) {
681 return WERR_NOT_ENOUGH_MEMORY;
683 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
684 if (tmp_dns_name == NULL) {
685 return WERR_NOT_ENOUGH_MEMORY;
687 s_dsa->other_info->dns_name = tmp_dns_name;
689 /* we want to show a count per partition */
690 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
691 s->total_objects = 0;
692 talloc_free(s->last_partition);
693 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
695 s->total_objects += object_count;
697 partition_dn = ldb_dn_new(s_dsa, s->ldb, c->partition->nc.dn);
698 if (partition_dn == NULL) {
699 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
700 return WERR_INVALID_PARAMETER;
703 if (is_exop) {
704 int ret;
705 if (nc_object_count) {
706 DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
707 c->partition->nc.dn, s->total_objects, nc_object_count,
708 linked_attributes_count, nc_linked_attributes_count));
709 } else {
710 DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
711 c->partition->nc.dn, s->total_objects, linked_attributes_count));
713 ret = dsdb_find_nc_root(s->ldb, s_dsa,
714 partition_dn, &nc_root);
715 if (ret != LDB_SUCCESS) {
716 DEBUG(0,(__location__ ": Failed to find nc_root for %s\n",
717 ldb_dn_get_linearized(partition_dn)));
718 return WERR_INTERNAL_ERROR;
720 } else {
721 if (nc_object_count) {
722 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
723 c->partition->nc.dn, s->total_objects, nc_object_count,
724 linked_attributes_count, nc_linked_attributes_count));
725 } else {
726 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
727 c->partition->nc.dn, s->total_objects, linked_attributes_count));
729 nc_root = partition_dn;
733 schema = dsdb_get_schema(s->ldb, NULL);
734 if (!schema) {
735 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
736 return WERR_INTERNAL_ERROR;
739 if (req_replica_flags & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS) {
740 dsdb_repl_flags |= DSDB_REPL_FLAG_PRIORITISE_INCOMING;
743 if (req_replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
744 dsdb_repl_flags |= DSDB_REPL_FLAG_EXPECT_NO_SECRETS;
747 status = dsdb_replicated_objects_convert(s->ldb,
748 schema,
749 nc_root,
750 mapping_ctr,
751 object_count,
752 first_object,
753 linked_attributes_count,
754 linked_attributes,
755 s_dsa,
756 uptodateness_vector,
757 c->gensec_skey,
758 dsdb_repl_flags,
759 s, &objs);
760 if (!W_ERROR_IS_OK(status)) {
761 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
762 return status;
765 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
766 for (i=0; i < objs->num_objects; i++) {
767 struct ldb_ldif ldif;
768 fprintf(stdout, "#\n");
769 ldif.changetype = LDB_CHANGETYPE_NONE;
770 ldif.msg = objs->objects[i].msg;
771 ldb_ldif_write_file(s->ldb, stdout, &ldif);
772 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
775 status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
776 if (!W_ERROR_IS_OK(status)) {
777 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
778 return status;
781 talloc_free(s_dsa);
782 talloc_free(objs);
784 for (i=0; i < linked_attributes_count; i++) {
785 const struct dsdb_attribute *sa;
787 if (!linked_attributes[i].identifier) {
788 DEBUG(0, ("No linked attribute identifier\n"));
789 return WERR_INTERNAL_ERROR;
792 if (!linked_attributes[i].value.blob) {
793 DEBUG(0, ("No linked attribute value\n"));
794 return WERR_INTERNAL_ERROR;
797 sa = dsdb_attribute_by_attributeID_id(s->schema,
798 linked_attributes[i].attid);
799 if (!sa) {
800 DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes[i].attid));
801 return WERR_INTERNAL_ERROR;
804 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
805 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
806 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
807 dump_data(0,
808 linked_attributes[i].value.blob->data,
809 linked_attributes[i].value.blob->length);
813 return WERR_OK;