nsswitch: fix use-after-free causing segfault in _pam_delete_cred
[Samba.git] / source4 / libnet / libnet_vampire.c
bloba0de1b7d3e005fa884cbed9652f2f8ad5e345d24
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 unsigned total_links;
92 char *last_partition;
93 const char *server_dn_str;
96 /* initialise a state structure ready for replication of chunks */
97 void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
98 struct ldb_context *samdb,
99 struct loadparm_context *lp_ctx)
101 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
102 if (!s) {
103 return NULL;
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);
114 return s;
117 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
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)
123 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
124 if (!s) {
125 return NULL;
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;
137 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
139 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
140 return state->ldb;
143 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
145 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
146 return state->lp_ctx;
149 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
150 const struct libnet_BecomeDC_PrepareDB *p)
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;
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);
172 if (!NT_STATUS_IS_OK(status)) {
173 return status;
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);
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;
194 return NT_STATUS_OK;
199 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
200 const struct libnet_BecomeDC_CheckOptions *o)
202 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
204 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
205 s->netbios_name,
206 o->domain->netbios_name, o->domain->dns_name));
208 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
209 o->source_dsa->dns_name, o->source_dsa->site_name));
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));
220 return NT_STATUS_OK;
223 static WERROR libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
224 const struct libnet_BecomeDC_StoreChunk *c)
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;
248 DEBUG(0,("Analyze and apply schema objects\n"));
250 s_dsa = talloc_zero(s, struct repsFromTo1);
251 if (s_dsa == NULL) {
252 return WERR_NOT_ENOUGH_MEMORY;
254 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
255 if (s_dsa->other_info == NULL) {
256 return WERR_NOT_ENOUGH_MEMORY;
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;
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;
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;
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;
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));
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;
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;
319 s_dsa->other_info->dns_name = tmp_dns_name;
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;
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;
340 talloc_unlink(s, schema_ldb);
343 cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
344 "become dc",
345 "schema convert retrial", 1);
347 provision_schema->resolving_in_progress = true;
348 s->self_made_schema->resolving_in_progress = true;
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;
363 /* free temp objects for 1st conversion phase */
364 talloc_unlink(s, provision_schema);
366 s->self_made_schema->resolving_in_progress = false;
369 * attach the schema we just brought over DRS to the ldb,
370 * so we can use it in dsdb_convert_object_ex below
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;
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;
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;
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,
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;
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);
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;
424 msg = ldb_msg_new(schema_objs);
425 if (msg == NULL) {
426 return WERR_NOT_ENOUGH_MEMORY;
428 msg->dn = schema_objs->partition_dn;
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;
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;
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;
450 talloc_free(s_dsa);
451 talloc_free(schema_objs);
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;
459 return WERR_OK;
462 WERROR libnet_vampire_cb_schema_chunk(void *private_data,
463 const struct libnet_BecomeDC_StoreChunk *c)
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;
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;
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;
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));
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 */
517 mapping_ctr_without_schema_info = *mapping_ctr;
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--;
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;
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;
538 werr = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
539 if (!W_ERROR_IS_OK(werr)) {
540 return werr;
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;
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);
557 if (first_object != NULL) {
558 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
559 } else {
560 cur = first_object;
563 s->schema_part.last_object = cur;
565 if (!c->partition->more_data) {
566 return libnet_vampire_cb_apply_schema(s, c);
569 return WERR_OK;
572 WERROR libnet_vampire_cb_store_chunk(void *private_data,
573 const struct libnet_BecomeDC_StoreChunk *c)
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;
597 s_dsa = talloc_zero(s, struct repsFromTo1);
598 if (s_dsa == NULL) {
599 return WERR_NOT_ENOUGH_MEMORY;
601 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
602 if (s_dsa->other_info == NULL) {
603 return WERR_NOT_ENOUGH_MEMORY;
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;
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;
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;
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;
658 req_replica_flags = c->req10->replica_flags;
660 if (c->req10->more_flags & DRSUAPI_DRS_GET_TGT) {
661 dsdb_repl_flags |= DSDB_REPL_FLAG_TARGETS_UPTODATE;
663 break;
664 default:
665 return WERR_INVALID_PARAMETER;
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)
673 if (c->req_level < 10) {
674 dsdb_repl_flags |= DSDB_REPL_FLAG_TARGETS_UPTODATE;
677 if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY || is_exop) {
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.
683 ZERO_STRUCT(s_dsa->highwatermark);
684 uptodateness_vector = NULL;
685 dsdb_repl_flags |= DSDB_REPL_FLAG_OBJECT_SUBSET;
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));
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;
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;
702 s_dsa->other_info->dns_name = tmp_dns_name;
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);
711 s->total_objects += object_count;
712 s->total_links += linked_attributes_count;
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;
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));
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;
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));
746 nc_root = partition_dn;
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;
756 if (req_replica_flags & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS) {
757 dsdb_repl_flags |= DSDB_REPL_FLAG_PRIORITISE_INCOMING;
760 if (req_replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
761 dsdb_repl_flags |= DSDB_REPL_FLAG_EXPECT_NO_SECRETS;
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;
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);
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;
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;
804 talloc_free(s_dsa);
805 talloc_free(objs);
807 for (i=0; i < linked_attributes_count; i++) {
808 const struct dsdb_attribute *sa;
810 if (!linked_attributes[i].identifier) {
811 DEBUG(0, ("No linked attribute identifier\n"));
812 return WERR_INTERNAL_ERROR;
815 if (!linked_attributes[i].value.blob) {
816 DEBUG(0, ("No linked attribute value\n"));
817 return WERR_INTERNAL_ERROR;
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;
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);
836 return WERR_OK;