samba.sites: reduce code duplication in Exception classes
[Samba.git] / source4 / libnet / libnet_vampire.c
blob97c6d1a009d481034005f20648843feecfae8585
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 /*
46 List of tasks vampire.py must perform:
47 - Domain Join
48 - but don't write the secrets.ldb
49 - results for this should be enough to handle the provision
50 - if vampire method is samsync
51 - Provision using these results
52 - do we still want to support this NT4 technology?
53 - Start samsync with libnet code
54 - provision in the callback
55 - Write out the secrets database, using the code from libnet_Join
58 struct libnet_vampire_cb_state {
59 const char *netbios_name;
60 const char *domain_name;
61 const char *realm;
62 struct cli_credentials *machine_account;
64 /* Schema loaded from local LDIF files */
65 struct dsdb_schema *provision_schema;
67 /* 1st pass, with some OIDs/attribute names/class names not
68 * converted, because we may not know them yet */
69 struct dsdb_schema *self_made_schema;
71 /* prefixMap in LDB format, from the remote DRS server */
72 DATA_BLOB prefixmap_blob;
73 const struct dsdb_schema *schema;
75 struct ldb_context *ldb;
77 struct {
78 uint32_t object_count;
79 struct drsuapi_DsReplicaObjectListItemEx *first_object;
80 struct drsuapi_DsReplicaObjectListItemEx *last_object;
81 } schema_part;
83 const char *targetdir;
85 struct loadparm_context *lp_ctx;
86 struct tevent_context *event_ctx;
87 unsigned total_objects;
88 char *last_partition;
89 const char *server_dn_str;
92 /* initialise a state structure ready for replication of chunks */
93 void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
94 struct ldb_context *samdb,
95 struct loadparm_context *lp_ctx)
97 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
98 if (!s) {
99 return NULL;
102 s->ldb = samdb;
103 s->lp_ctx = lp_ctx;
104 s->provision_schema = dsdb_get_schema(s->ldb, s);
105 s->schema = s->provision_schema;
106 s->netbios_name = lpcfg_netbios_name(lp_ctx);
107 s->domain_name = lpcfg_workgroup(lp_ctx);
108 s->realm = lpcfg_realm(lp_ctx);
110 return s;
113 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
114 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
115 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
116 const char *netbios_name, const char *domain_name, const char *realm,
117 const char *targetdir)
119 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
120 if (!s) {
121 return NULL;
124 s->lp_ctx = lp_ctx;
125 s->event_ctx = event_ctx;
126 s->netbios_name = netbios_name;
127 s->domain_name = domain_name;
128 s->realm = realm;
129 s->targetdir = targetdir;
130 return s;
133 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
135 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
136 return state->ldb;
139 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
141 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
142 return state->lp_ctx;
145 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
146 const struct libnet_BecomeDC_PrepareDB *p)
148 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
149 struct provision_settings settings;
150 struct provision_result result;
151 NTSTATUS status;
153 ZERO_STRUCT(settings);
154 settings.site_name = p->dest_dsa->site_name;
155 settings.root_dn_str = p->forest->root_dn_str;
156 settings.domain_dn_str = p->domain->dn_str;
157 settings.config_dn_str = p->forest->config_dn_str;
158 settings.schema_dn_str = p->forest->schema_dn_str;
159 settings.netbios_name = p->dest_dsa->netbios_name;
160 settings.realm = s->realm;
161 settings.domain = s->domain_name;
162 settings.server_dn_str = p->dest_dsa->server_dn_str;
163 settings.machine_password = generate_random_password(s, 16, 255);
164 settings.targetdir = s->targetdir;
165 settings.use_ntvfs = true;
166 status = provision_bare(s, s->lp_ctx, &settings, &result);
168 if (!NT_STATUS_IS_OK(status)) {
169 return status;
172 s->ldb = talloc_steal(s, result.samdb);
173 s->lp_ctx = talloc_reparent(talloc_parent(result.lp_ctx), s, result.lp_ctx);
174 s->provision_schema = dsdb_get_schema(s->ldb, s);
175 s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
177 /* wrap the entire vapire operation in a transaction. This
178 isn't just cosmetic - we use this to ensure that linked
179 attribute back links are added at the end by relying on a
180 transaction commit hook in the linked attributes module. We
181 need to do this as the order of objects coming from the
182 server is not sufficiently deterministic to know that the
183 record that a backlink needs to be created in has itself
184 been created before the object containing the forward link
185 has come over the wire */
186 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
187 return NT_STATUS_FOOBAR;
190 return NT_STATUS_OK;
195 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
196 const struct libnet_BecomeDC_CheckOptions *o)
198 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
200 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
201 s->netbios_name,
202 o->domain->netbios_name, o->domain->dns_name));
204 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
205 o->source_dsa->dns_name, o->source_dsa->site_name));
207 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
208 "\tschema object_version[%u]\n"
209 "\tdomain behavior_version[%u]\n"
210 "\tdomain w2k3_update_revision[%u]\n",
211 o->forest->crossref_behavior_version,
212 o->forest->schema_object_version,
213 o->domain->behavior_version,
214 o->domain->w2k3_update_revision));
216 return NT_STATUS_OK;
219 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
220 const struct libnet_BecomeDC_StoreChunk *c)
222 WERROR status;
223 struct dsdb_schema_prefixmap *pfm_remote;
224 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
225 struct dsdb_schema *provision_schema;
226 uint32_t object_count = 0;
227 struct drsuapi_DsReplicaObjectListItemEx *first_object;
228 uint32_t linked_attributes_count;
229 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
230 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
231 struct dsdb_extended_replicated_objects *schema_objs;
232 struct repsFromTo1 *s_dsa;
233 char *tmp_dns_name;
234 struct ldb_context *schema_ldb;
235 struct ldb_message *msg;
236 struct ldb_message_element *prefixMap_el;
237 uint32_t i;
238 int ret;
239 bool ok;
240 uint64_t seq_num;
241 uint32_t cycle_before_switching;
243 DEBUG(0,("Analyze and apply schema objects\n"));
245 s_dsa = talloc_zero(s, struct repsFromTo1);
246 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
247 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
248 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
250 switch (c->ctr_level) {
251 case 1:
252 mapping_ctr = &c->ctr1->mapping_ctr;
253 object_count = s->schema_part.object_count;
254 first_object = s->schema_part.first_object;
255 linked_attributes_count = 0;
256 linked_attributes = NULL;
257 s_dsa->highwatermark = c->ctr1->new_highwatermark;
258 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
259 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
260 uptodateness_vector = NULL; /* TODO: map it */
261 break;
262 case 6:
263 mapping_ctr = &c->ctr6->mapping_ctr;
264 object_count = s->schema_part.object_count;
265 first_object = s->schema_part.first_object;
266 linked_attributes_count = c->ctr6->linked_attributes_count;
267 linked_attributes = c->ctr6->linked_attributes;
268 s_dsa->highwatermark = c->ctr6->new_highwatermark;
269 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
270 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
271 uptodateness_vector = c->ctr6->uptodateness_vector;
272 break;
273 default:
274 return NT_STATUS_INVALID_PARAMETER;
276 /* We must set these up to ensure the replMetaData is written
277 * correctly, before our NTDS Settings entry is replicated */
278 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
279 if (!ok) {
280 DEBUG(0,("Failed to set cached ntds invocationId\n"));
281 return NT_STATUS_FOOBAR;
283 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
284 if (!ok) {
285 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
286 return NT_STATUS_FOOBAR;
289 status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
290 s, &pfm_remote, NULL);
291 if (!W_ERROR_IS_OK(status)) {
292 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
293 win_errstr(status)));
294 return werror_to_ntstatus(status);
297 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
298 | DRSUAPI_DRS_INIT_SYNC
299 | DRSUAPI_DRS_PER_SYNC;
300 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
302 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
303 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
304 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
305 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
306 s_dsa->other_info->dns_name = tmp_dns_name;
308 if (s->self_made_schema == NULL) {
309 DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
310 return NT_STATUS_INTERNAL_ERROR;
313 schema_ldb = provision_get_schema(s, s->lp_ctx,
314 c->forest->schema_dn_str,
315 &s->prefixmap_blob);
316 if (!schema_ldb) {
317 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
318 "Will continue with local prefixMap\n"));
319 provision_schema = dsdb_get_schema(s->ldb, s);
320 } else {
321 provision_schema = dsdb_get_schema(schema_ldb, s);
322 ret = dsdb_reference_schema(s->ldb, provision_schema, false);
323 if (ret != LDB_SUCCESS) {
324 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
325 return NT_STATUS_UNSUCCESSFUL;
327 talloc_free(schema_ldb);
330 cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
331 "become dc",
332 "schema convert retrial", 1);
334 status = dsdb_repl_resolve_working_schema(s->ldb, s,
335 pfm_remote,
336 cycle_before_switching,
337 provision_schema,
338 s->self_made_schema,
339 object_count,
340 first_object);
341 if (!W_ERROR_IS_OK(status)) {
342 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
343 __location__, win_errstr(status)));
344 return werror_to_ntstatus(status);
347 /* free temp objects for 1st conversion phase */
348 talloc_unlink(s, provision_schema);
351 * attach the schema we just brought over DRS to the ldb,
352 * so we can use it in dsdb_convert_object_ex below
354 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
355 if (ret != LDB_SUCCESS) {
356 DEBUG(0,("Failed to attach working schema from DRS.\n"));
357 return NT_STATUS_FOOBAR;
360 /* we don't want to access the self made schema anymore */
361 s->schema = s->self_made_schema;
362 s->self_made_schema = NULL;
364 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
365 status = dsdb_replicated_objects_convert(s->ldb,
366 s->schema,
367 c->partition->nc.dn,
368 mapping_ctr,
369 object_count,
370 first_object,
371 linked_attributes_count,
372 linked_attributes,
373 s_dsa,
374 uptodateness_vector,
375 c->gensec_skey,
377 s, &schema_objs);
378 if (!W_ERROR_IS_OK(status)) {
379 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
380 return werror_to_ntstatus(status);
383 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
384 for (i=0; i < schema_objs->num_objects; i++) {
385 struct ldb_ldif ldif;
386 fprintf(stdout, "#\n");
387 ldif.changetype = LDB_CHANGETYPE_NONE;
388 ldif.msg = schema_objs->objects[i].msg;
389 ldb_ldif_write_file(s->ldb, stdout, &ldif);
390 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
394 status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
395 if (!W_ERROR_IS_OK(status)) {
396 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
397 return werror_to_ntstatus(status);
400 msg = ldb_msg_new(schema_objs);
401 NT_STATUS_HAVE_NO_MEMORY(msg);
402 msg->dn = schema_objs->partition_dn;
404 /* We must ensure a prefixMap has been written. Unlike other
405 * attributes (including schemaInfo), it is not replicated in
406 * the normal replication stream. We can use the one from
407 * s->prefixmap_blob because we operate with one, unchanging
408 * prefixMap for this entire operation. */
409 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
410 if (ret != LDB_SUCCESS) {
411 return NT_STATUS_FOOBAR;
413 /* We want to know if a prefixMap was written already, as it
414 * would mean that the above comment was not true, and we have
415 * somehow updated the prefixMap during this transaction */
416 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
418 ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
419 if (ret != LDB_SUCCESS) {
420 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
421 return NT_STATUS_FOOBAR;
424 talloc_free(s_dsa);
425 talloc_free(schema_objs);
427 s->schema = dsdb_get_schema(s->ldb, s);
428 if (!s->schema) {
429 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
430 return NT_STATUS_FOOBAR;
433 return NT_STATUS_OK;
436 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
437 const struct libnet_BecomeDC_StoreChunk *c)
439 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
440 WERROR status;
441 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
442 uint32_t nc_object_count;
443 uint32_t nc_total_received = 0;
444 uint32_t object_count;
445 struct drsuapi_DsReplicaObjectListItemEx *first_object;
446 struct drsuapi_DsReplicaObjectListItemEx *cur;
447 uint32_t nc_linked_attributes_count;
448 uint32_t linked_attributes_count;
450 switch (c->ctr_level) {
451 case 1:
452 mapping_ctr = &c->ctr1->mapping_ctr;
453 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
454 object_count = c->ctr1->object_count;
455 first_object = c->ctr1->first_object;
456 nc_linked_attributes_count = 0;
457 linked_attributes_count = 0;
458 break;
459 case 6:
460 mapping_ctr = &c->ctr6->mapping_ctr;
461 nc_object_count = c->ctr6->nc_object_count;
462 object_count = c->ctr6->object_count;
463 first_object = c->ctr6->first_object;
464 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
465 linked_attributes_count = c->ctr6->linked_attributes_count;
466 break;
467 default:
468 return NT_STATUS_INVALID_PARAMETER;
471 if (!s->schema_part.first_object) {
472 nc_total_received = object_count;
473 } else {
474 nc_total_received = s->schema_part.object_count + object_count;
476 if (nc_object_count) {
477 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
478 c->partition->nc.dn, nc_total_received, nc_object_count,
479 linked_attributes_count, nc_linked_attributes_count));
480 } else {
481 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
482 c->partition->nc.dn, nc_total_received, linked_attributes_count));
485 if (!s->self_made_schema) {
486 WERROR werr;
487 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
488 /* Put the DRS prefixmap aside for the schema we are
489 * about to load in the provision, and into the one we
490 * are making with the help of DRS */
492 mapping_ctr_without_schema_info = *mapping_ctr;
494 /* This strips off the 0xFF schema info from the end,
495 * because we don't want it in the blob */
496 if (mapping_ctr_without_schema_info.num_mappings > 0) {
497 mapping_ctr_without_schema_info.num_mappings--;
499 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
500 if (!W_ERROR_IS_OK(werr)) {
501 return werror_to_ntstatus(werr);
504 /* Set up two manually-constructed schema - the local
505 * schema from the provision will be used to build
506 * one, which will then in turn be used to build the
507 * other. */
508 s->self_made_schema = dsdb_new_schema(s);
509 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
511 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
512 if (!W_ERROR_IS_OK(status)) {
513 return werror_to_ntstatus(status);
515 } else {
516 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
517 if (!W_ERROR_IS_OK(status)) {
518 return werror_to_ntstatus(status);
522 if (!s->schema_part.first_object) {
523 s->schema_part.object_count = object_count;
524 s->schema_part.first_object = talloc_steal(s, first_object);
525 } else {
526 s->schema_part.object_count += object_count;
527 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
528 first_object);
530 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
531 s->schema_part.last_object = cur;
533 if (!c->partition->more_data) {
534 return libnet_vampire_cb_apply_schema(s, c);
537 return NT_STATUS_OK;
540 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
541 const struct libnet_BecomeDC_StoreChunk *c)
543 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
544 WERROR status;
545 struct dsdb_schema *schema;
546 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
547 uint32_t nc_object_count;
548 uint32_t object_count;
549 struct drsuapi_DsReplicaObjectListItemEx *first_object;
550 uint32_t nc_linked_attributes_count;
551 uint32_t linked_attributes_count;
552 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
553 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
554 struct dsdb_extended_replicated_objects *objs;
555 uint32_t req_replica_flags;
556 uint32_t dsdb_repl_flags = 0;
557 struct repsFromTo1 *s_dsa;
558 char *tmp_dns_name;
559 uint32_t i;
560 uint64_t seq_num;
561 bool is_exop = false;
563 s_dsa = talloc_zero(s, struct repsFromTo1);
564 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
565 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
566 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
568 switch (c->ctr_level) {
569 case 1:
570 mapping_ctr = &c->ctr1->mapping_ctr;
571 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
572 object_count = c->ctr1->object_count;
573 first_object = c->ctr1->first_object;
574 nc_linked_attributes_count = 0;
575 linked_attributes_count = 0;
576 linked_attributes = NULL;
577 s_dsa->highwatermark = c->ctr1->new_highwatermark;
578 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
579 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
580 uptodateness_vector = NULL; /* TODO: map it */
581 break;
582 case 6:
583 mapping_ctr = &c->ctr6->mapping_ctr;
584 nc_object_count = c->ctr6->nc_object_count;
585 object_count = c->ctr6->object_count;
586 first_object = c->ctr6->first_object;
587 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
588 linked_attributes_count = c->ctr6->linked_attributes_count;
589 linked_attributes = c->ctr6->linked_attributes;
590 s_dsa->highwatermark = c->ctr6->new_highwatermark;
591 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
592 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
593 uptodateness_vector = c->ctr6->uptodateness_vector;
594 break;
595 default:
596 return NT_STATUS_INVALID_PARAMETER;
599 switch (c->req_level) {
600 case 0:
601 /* none */
602 req_replica_flags = 0;
603 break;
604 case 5:
605 if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
606 is_exop = true;
608 req_replica_flags = c->req5->replica_flags;
609 break;
610 case 8:
611 if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
612 is_exop = true;
614 req_replica_flags = c->req8->replica_flags;
615 break;
616 case 10:
617 if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
618 is_exop = true;
620 req_replica_flags = c->req10->replica_flags;
621 break;
622 default:
623 return NT_STATUS_INVALID_PARAMETER;
626 if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
628 * If we only replicate the critical objects
629 * we should not remember what we already
630 * got, as it is incomplete.
632 ZERO_STRUCT(s_dsa->highwatermark);
633 uptodateness_vector = NULL;
636 /* TODO: avoid hardcoded flags */
637 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
638 | DRSUAPI_DRS_INIT_SYNC
639 | DRSUAPI_DRS_PER_SYNC;
640 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
642 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
643 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
644 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
645 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
646 s_dsa->other_info->dns_name = tmp_dns_name;
648 /* we want to show a count per partition */
649 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
650 s->total_objects = 0;
651 talloc_free(s->last_partition);
652 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
654 s->total_objects += object_count;
656 if (is_exop) {
657 if (nc_object_count) {
658 DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
659 c->partition->nc.dn, s->total_objects, nc_object_count,
660 linked_attributes_count, nc_linked_attributes_count));
661 } else {
662 DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
663 c->partition->nc.dn, s->total_objects, linked_attributes_count));
665 } else {
666 if (nc_object_count) {
667 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
668 c->partition->nc.dn, s->total_objects, nc_object_count,
669 linked_attributes_count, nc_linked_attributes_count));
670 } else {
671 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
672 c->partition->nc.dn, s->total_objects, linked_attributes_count));
677 schema = dsdb_get_schema(s->ldb, NULL);
678 if (!schema) {
679 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
680 return NT_STATUS_INTERNAL_ERROR;
683 if (req_replica_flags & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS) {
684 dsdb_repl_flags |= DSDB_REPL_FLAG_PRIORITISE_INCOMING;
687 if (req_replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
688 dsdb_repl_flags |= DSDB_REPL_FLAG_EXPECT_NO_SECRETS;
691 status = dsdb_replicated_objects_convert(s->ldb,
692 schema,
693 c->partition->nc.dn,
694 mapping_ctr,
695 object_count,
696 first_object,
697 linked_attributes_count,
698 linked_attributes,
699 s_dsa,
700 uptodateness_vector,
701 c->gensec_skey,
702 dsdb_repl_flags,
703 s, &objs);
704 if (!W_ERROR_IS_OK(status)) {
705 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
706 return werror_to_ntstatus(status);
709 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
710 for (i=0; i < objs->num_objects; i++) {
711 struct ldb_ldif ldif;
712 fprintf(stdout, "#\n");
713 ldif.changetype = LDB_CHANGETYPE_NONE;
714 ldif.msg = objs->objects[i].msg;
715 ldb_ldif_write_file(s->ldb, stdout, &ldif);
716 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
719 status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
720 if (!W_ERROR_IS_OK(status)) {
721 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
722 return werror_to_ntstatus(status);
725 talloc_free(s_dsa);
726 talloc_free(objs);
728 for (i=0; i < linked_attributes_count; i++) {
729 const struct dsdb_attribute *sa;
731 if (!linked_attributes[i].identifier) {
732 DEBUG(0, ("No linked attribute identifier\n"));
733 return NT_STATUS_FOOBAR;
736 if (!linked_attributes[i].value.blob) {
737 DEBUG(0, ("No linked attribute value\n"));
738 return NT_STATUS_FOOBAR;
741 sa = dsdb_attribute_by_attributeID_id(s->schema,
742 linked_attributes[i].attid);
743 if (!sa) {
744 DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes[i].attid));
745 return NT_STATUS_FOOBAR;
748 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
749 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
750 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
751 dump_data(0,
752 linked_attributes[i].value.blob->data,
753 linked_attributes[i].value.blob->length);
757 return NT_STATUS_OK;