libnet: set the invocation_id earlier in order to avoid annoying messages
[Samba.git] / source4 / libnet / libnet_vampire.c
bloba354d41e3895df9d5446a2db1f7cc490bdede78e
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 struct schema_list {
223 struct schema_list *next, *prev;
224 const struct drsuapi_DsReplicaObjectListItemEx *obj;
227 WERROR status;
228 struct dsdb_schema_prefixmap *pfm_remote;
229 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
230 struct schema_list *schema_list = NULL, *schema_list_item, *schema_list_next_item;
231 struct dsdb_schema *working_schema;
232 struct dsdb_schema *provision_schema;
233 uint32_t object_count = 0;
234 struct drsuapi_DsReplicaObjectListItemEx *first_object;
235 const struct drsuapi_DsReplicaObjectListItemEx *cur;
236 uint32_t linked_attributes_count;
237 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
238 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
239 struct dsdb_extended_replicated_objects *schema_objs;
240 struct repsFromTo1 *s_dsa;
241 char *tmp_dns_name;
242 struct ldb_context *schema_ldb;
243 struct ldb_message *msg;
244 struct ldb_message_element *prefixMap_el;
245 uint32_t i;
246 int ret, pass_no;
247 bool ok;
248 uint64_t seq_num;
249 uint32_t ignore_attids[] = {
250 DRSUAPI_ATTID_auxiliaryClass,
251 DRSUAPI_ATTID_mayContain,
252 DRSUAPI_ATTID_mustContain,
253 DRSUAPI_ATTID_possSuperiors,
254 DRSUAPI_ATTID_systemPossSuperiors,
255 DRSUAPI_ATTID_INVALID
258 DEBUG(0,("Analyze and apply schema objects\n"));
260 s_dsa = talloc_zero(s, struct repsFromTo1);
261 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
262 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
263 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
265 switch (c->ctr_level) {
266 case 1:
267 mapping_ctr = &c->ctr1->mapping_ctr;
268 object_count = s->schema_part.object_count;
269 first_object = s->schema_part.first_object;
270 linked_attributes_count = 0;
271 linked_attributes = NULL;
272 s_dsa->highwatermark = c->ctr1->new_highwatermark;
273 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
274 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
275 uptodateness_vector = NULL; /* TODO: map it */
276 break;
277 case 6:
278 mapping_ctr = &c->ctr6->mapping_ctr;
279 object_count = s->schema_part.object_count;
280 first_object = s->schema_part.first_object;
281 linked_attributes_count = c->ctr6->linked_attributes_count;
282 linked_attributes = c->ctr6->linked_attributes;
283 s_dsa->highwatermark = c->ctr6->new_highwatermark;
284 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
285 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
286 uptodateness_vector = c->ctr6->uptodateness_vector;
287 break;
288 default:
289 return NT_STATUS_INVALID_PARAMETER;
291 /* We must set these up to ensure the replMetaData is written
292 * correctly, before our NTDS Settings entry is replicated */
293 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
294 if (!ok) {
295 DEBUG(0,("Failed to set cached ntds invocationId\n"));
296 return NT_STATUS_FOOBAR;
298 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
299 if (!ok) {
300 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
301 return NT_STATUS_FOOBAR;
305 status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
306 s, &pfm_remote, NULL);
307 if (!W_ERROR_IS_OK(status)) {
308 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
309 win_errstr(status)));
310 return werror_to_ntstatus(status);
313 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
314 | DRSUAPI_DRS_INIT_SYNC
315 | DRSUAPI_DRS_PER_SYNC;
316 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
318 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
319 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
320 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
321 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
322 s_dsa->other_info->dns_name = tmp_dns_name;
324 schema_ldb = provision_get_schema(s, s->lp_ctx,
325 c->forest->schema_dn_str,
326 &s->prefixmap_blob);
327 if (!schema_ldb) {
328 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
329 "Will continue with local prefixMap\n"));
330 provision_schema = dsdb_get_schema(s->ldb, s);
331 } else {
332 provision_schema = dsdb_get_schema(schema_ldb, s);
333 ret = dsdb_reference_schema(s->ldb, provision_schema, false);
334 if (ret != LDB_SUCCESS) {
335 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
336 return NT_STATUS_UNSUCCESSFUL;
338 talloc_free(schema_ldb);
341 /* create a list of objects yet to be converted */
342 for (cur = first_object; cur; cur = cur->next_object) {
343 schema_list_item = talloc(s, struct schema_list);
344 schema_list_item->obj = cur;
345 DLIST_ADD_END(schema_list, schema_list_item, struct schema_list);
348 /* resolve objects until all are resolved and in local schema */
349 pass_no = 1;
350 working_schema = provision_schema;
352 while (schema_list) {
353 uint32_t converted_obj_count = 0;
354 uint32_t failed_obj_count = 0;
355 TALLOC_CTX *tmp_ctx = talloc_new(s);
356 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
358 for (schema_list_item = schema_list; schema_list_item; schema_list_item=schema_list_next_item) {
359 struct dsdb_extended_replicated_object object;
361 cur = schema_list_item->obj;
363 /* Save the next item, now we have saved out
364 * the current one, so we can DLIST_REMOVE it
365 * safely */
366 schema_list_next_item = schema_list_item->next;
369 * Convert the objects into LDB messages using the
370 * schema we have so far. It's ok if we fail to convert
371 * an object. We should convert more objects on next pass.
373 status = dsdb_convert_object_ex(s->ldb, working_schema, pfm_remote,
374 cur, c->gensec_skey,
375 ignore_attids,
377 tmp_ctx, &object);
378 if (!W_ERROR_IS_OK(status)) {
379 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n",
380 cur->object.identifier->dn));
382 failed_obj_count++;
383 } else {
385 * Convert the schema from ldb_message format
386 * (OIDs as OID strings) into schema, using
387 * the remote prefixMap
389 status = dsdb_schema_set_el_from_ldb_msg(s->ldb,
390 s->self_made_schema,
391 object.msg);
392 if (!W_ERROR_IS_OK(status)) {
393 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
394 ldb_dn_get_linearized(object.msg->dn),
395 win_errstr(status)));
396 failed_obj_count++;
397 } else {
398 DLIST_REMOVE(schema_list, schema_list_item);
399 converted_obj_count++;
403 talloc_free(tmp_ctx);
405 DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n",
406 pass_no, failed_obj_count, converted_obj_count, object_count));
407 pass_no++;
409 /* check if we converted any objects in this pass */
410 if (converted_obj_count == 0) {
411 DEBUG(0,("Can't continue Schema load: didn't manage to convert any objects: all %d remaining of %d objects failed to convert\n", failed_obj_count, object_count));
412 return NT_STATUS_INTERNAL_ERROR;
415 if (schema_list) {
416 /* prepare for another cycle */
417 working_schema = s->self_made_schema;
419 ret = dsdb_setup_sorted_accessors(s->ldb, working_schema);
420 if (LDB_SUCCESS != ret) {
421 DEBUG(0,("Failed to create schema-cache indexes!\n"));
422 return NT_STATUS_INTERNAL_ERROR;
427 /* free temp objects for 1st conversion phase */
428 talloc_unlink(s, provision_schema);
429 TALLOC_FREE(schema_list);
432 * attach the schema we just brought over DRS to the ldb,
433 * so we can use it in dsdb_convert_object_ex below
435 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
436 if (ret != LDB_SUCCESS) {
437 DEBUG(0,("Failed to attach working schema from DRS.\n"));
438 return NT_STATUS_FOOBAR;
441 /* we don't want to access the self made schema anymore */
442 s->schema = s->self_made_schema;
443 s->self_made_schema = NULL;
445 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
446 status = dsdb_replicated_objects_convert(s->ldb,
447 s->schema,
448 c->partition->nc.dn,
449 mapping_ctr,
450 object_count,
451 first_object,
452 linked_attributes_count,
453 linked_attributes,
454 s_dsa,
455 uptodateness_vector,
456 c->gensec_skey,
458 s, &schema_objs);
459 if (!W_ERROR_IS_OK(status)) {
460 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
461 return werror_to_ntstatus(status);
464 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
465 for (i=0; i < schema_objs->num_objects; i++) {
466 struct ldb_ldif ldif;
467 fprintf(stdout, "#\n");
468 ldif.changetype = LDB_CHANGETYPE_NONE;
469 ldif.msg = schema_objs->objects[i].msg;
470 ldb_ldif_write_file(s->ldb, stdout, &ldif);
471 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
475 status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
476 if (!W_ERROR_IS_OK(status)) {
477 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
478 return werror_to_ntstatus(status);
481 msg = ldb_msg_new(schema_objs);
482 NT_STATUS_HAVE_NO_MEMORY(msg);
483 msg->dn = schema_objs->partition_dn;
485 /* We must ensure a prefixMap has been written. Unlike other
486 * attributes (including schemaInfo), it is not replicated in
487 * the normal replication stream. We can use the one from
488 * s->prefixmap_blob because we operate with one, unchanging
489 * prefixMap for this entire operation. */
490 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
491 if (ret != LDB_SUCCESS) {
492 return NT_STATUS_FOOBAR;
494 /* We want to know if a prefixMap was written already, as it
495 * would mean that the above comment was not true, and we have
496 * somehow updated the prefixMap during this transaction */
497 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
499 ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
500 if (ret != LDB_SUCCESS) {
501 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
502 return NT_STATUS_FOOBAR;
505 talloc_free(s_dsa);
506 talloc_free(schema_objs);
508 s->schema = dsdb_get_schema(s->ldb, s);
509 if (!s->schema) {
510 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
511 return NT_STATUS_FOOBAR;
514 return NT_STATUS_OK;
517 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
518 const struct libnet_BecomeDC_StoreChunk *c)
520 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
521 WERROR status;
522 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
523 uint32_t nc_object_count;
524 uint32_t nc_total_received = 0;
525 uint32_t object_count;
526 struct drsuapi_DsReplicaObjectListItemEx *first_object;
527 struct drsuapi_DsReplicaObjectListItemEx *cur;
528 uint32_t nc_linked_attributes_count;
529 uint32_t linked_attributes_count;
531 switch (c->ctr_level) {
532 case 1:
533 mapping_ctr = &c->ctr1->mapping_ctr;
534 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
535 object_count = c->ctr1->object_count;
536 first_object = c->ctr1->first_object;
537 nc_linked_attributes_count = 0;
538 linked_attributes_count = 0;
539 break;
540 case 6:
541 mapping_ctr = &c->ctr6->mapping_ctr;
542 nc_object_count = c->ctr6->nc_object_count;
543 object_count = c->ctr6->object_count;
544 first_object = c->ctr6->first_object;
545 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
546 linked_attributes_count = c->ctr6->linked_attributes_count;
547 break;
548 default:
549 return NT_STATUS_INVALID_PARAMETER;
552 if (!s->schema_part.first_object) {
553 nc_total_received = object_count;
554 } else {
555 nc_total_received = s->schema_part.object_count + object_count;
557 if (nc_object_count) {
558 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
559 c->partition->nc.dn, nc_total_received, nc_object_count,
560 linked_attributes_count, nc_linked_attributes_count));
561 } else {
562 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
563 c->partition->nc.dn, nc_total_received, linked_attributes_count));
566 if (!s->self_made_schema) {
567 WERROR werr;
568 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
569 /* Put the DRS prefixmap aside for the schema we are
570 * about to load in the provision, and into the one we
571 * are making with the help of DRS */
573 mapping_ctr_without_schema_info = *mapping_ctr;
575 /* This strips off the 0xFF schema info from the end,
576 * because we don't want it in the blob */
577 if (mapping_ctr_without_schema_info.num_mappings > 0) {
578 mapping_ctr_without_schema_info.num_mappings--;
580 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
581 if (!W_ERROR_IS_OK(werr)) {
582 return werror_to_ntstatus(werr);
585 /* Set up two manually-constructed schema - the local
586 * schema from the provision will be used to build
587 * one, which will then in turn be used to build the
588 * other. */
589 s->self_made_schema = dsdb_new_schema(s);
590 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
592 s->self_made_schema->base_dn = ldb_dn_new(s->self_made_schema,
593 s->ldb,
594 c->forest->schema_dn_str);
595 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema->base_dn);
597 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
598 if (!W_ERROR_IS_OK(status)) {
599 return werror_to_ntstatus(status);
601 } else {
602 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
603 if (!W_ERROR_IS_OK(status)) {
604 return werror_to_ntstatus(status);
608 if (!s->schema_part.first_object) {
609 s->schema_part.object_count = object_count;
610 s->schema_part.first_object = talloc_steal(s, first_object);
611 } else {
612 s->schema_part.object_count += object_count;
613 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
614 first_object);
616 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
617 s->schema_part.last_object = cur;
619 if (!c->partition->more_data) {
620 return libnet_vampire_cb_apply_schema(s, c);
623 return NT_STATUS_OK;
626 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
627 const struct libnet_BecomeDC_StoreChunk *c)
629 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
630 WERROR status;
631 struct dsdb_schema *schema;
632 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
633 uint32_t nc_object_count;
634 uint32_t object_count;
635 struct drsuapi_DsReplicaObjectListItemEx *first_object;
636 uint32_t nc_linked_attributes_count;
637 uint32_t linked_attributes_count;
638 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
639 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
640 struct dsdb_extended_replicated_objects *objs;
641 uint32_t req_replica_flags;
642 struct repsFromTo1 *s_dsa;
643 char *tmp_dns_name;
644 uint32_t i;
645 uint64_t seq_num;
647 s_dsa = talloc_zero(s, struct repsFromTo1);
648 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
649 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
650 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
652 switch (c->ctr_level) {
653 case 1:
654 mapping_ctr = &c->ctr1->mapping_ctr;
655 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
656 object_count = c->ctr1->object_count;
657 first_object = c->ctr1->first_object;
658 nc_linked_attributes_count = 0;
659 linked_attributes_count = 0;
660 linked_attributes = NULL;
661 s_dsa->highwatermark = c->ctr1->new_highwatermark;
662 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
663 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
664 uptodateness_vector = NULL; /* TODO: map it */
665 break;
666 case 6:
667 mapping_ctr = &c->ctr6->mapping_ctr;
668 nc_object_count = c->ctr6->nc_object_count;
669 object_count = c->ctr6->object_count;
670 first_object = c->ctr6->first_object;
671 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
672 linked_attributes_count = c->ctr6->linked_attributes_count;
673 linked_attributes = c->ctr6->linked_attributes;
674 s_dsa->highwatermark = c->ctr6->new_highwatermark;
675 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
676 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
677 uptodateness_vector = c->ctr6->uptodateness_vector;
678 break;
679 default:
680 return NT_STATUS_INVALID_PARAMETER;
683 switch (c->req_level) {
684 case 0:
685 /* none */
686 req_replica_flags = 0;
687 break;
688 case 5:
689 req_replica_flags = c->req5->replica_flags;
690 break;
691 case 8:
692 req_replica_flags = c->req8->replica_flags;
693 break;
694 case 10:
695 req_replica_flags = c->req10->replica_flags;
696 break;
697 default:
698 return NT_STATUS_INVALID_PARAMETER;
701 if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
703 * If we only replicate the critical objects
704 * we should not remember what we already
705 * got, as it is incomplete.
707 ZERO_STRUCT(s_dsa->highwatermark);
708 uptodateness_vector = NULL;
711 /* TODO: avoid hardcoded flags */
712 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
713 | DRSUAPI_DRS_INIT_SYNC
714 | DRSUAPI_DRS_PER_SYNC;
715 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
717 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
718 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
719 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
720 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
721 s_dsa->other_info->dns_name = tmp_dns_name;
723 /* we want to show a count per partition */
724 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
725 s->total_objects = 0;
726 talloc_free(s->last_partition);
727 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
729 s->total_objects += object_count;
731 if (nc_object_count) {
732 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
733 c->partition->nc.dn, s->total_objects, nc_object_count,
734 linked_attributes_count, nc_linked_attributes_count));
735 } else {
736 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
737 c->partition->nc.dn, s->total_objects, linked_attributes_count));
741 schema = dsdb_get_schema(s->ldb, NULL);
742 if (!schema) {
743 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
744 return NT_STATUS_INTERNAL_ERROR;
747 status = dsdb_replicated_objects_convert(s->ldb,
748 schema,
749 c->partition->nc.dn,
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,
759 s, &objs);
760 if (!W_ERROR_IS_OK(status)) {
761 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
762 return werror_to_ntstatus(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 werror_to_ntstatus(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 NT_STATUS_FOOBAR;
792 if (!linked_attributes[i].value.blob) {
793 DEBUG(0, ("No linked attribute value\n"));
794 return NT_STATUS_FOOBAR;
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 NT_STATUS_FOOBAR;
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 NT_STATUS_OK;
816 static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
817 struct ldb_context *ldb,
818 const char *server_dn_str,
819 const char *netbios_name,
820 const char *realm)
822 int ret;
823 struct ldb_message *msg;
824 struct ldb_message_element *el;
825 struct ldb_dn *server_dn;
826 const char *dNSHostName = strlower_talloc(mem_ctx,
827 talloc_asprintf(mem_ctx,
828 "%s.%s",
829 netbios_name,
830 realm));
831 msg = ldb_msg_new(mem_ctx);
832 if (msg == NULL) {
833 return NT_STATUS_NO_MEMORY;
836 server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
837 if (!server_dn) {
838 return NT_STATUS_INTERNAL_ERROR;
841 msg->dn = server_dn;
842 ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
843 if (ret != LDB_SUCCESS) {
844 return NT_STATUS_INTERNAL_ERROR;
847 ret = ldb_msg_add_steal_string(msg,
848 "dNSHostName",
849 talloc_asprintf(el->values, "%s", dNSHostName));
850 if (ret != LDB_SUCCESS) {
851 return NT_STATUS_INTERNAL_ERROR;
854 ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
855 if (ret != LDB_SUCCESS) {
856 DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
857 ldb_errstring(ldb)));
858 return NT_STATUS_INTERNAL_ERROR;
861 return NT_STATUS_OK;
865 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
866 struct libnet_Vampire *r)
868 struct libnet_JoinDomain *join;
869 struct libnet_Replicate rep;
870 NTSTATUS status;
872 const char *account_name;
873 const char *netbios_name;
875 r->out.error_string = NULL;
877 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
878 if (!join) {
879 return NT_STATUS_NO_MEMORY;
882 if (r->in.netbios_name != NULL) {
883 netbios_name = r->in.netbios_name;
884 } else {
885 netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
886 if (!netbios_name) {
887 talloc_free(join);
888 r->out.error_string = NULL;
889 return NT_STATUS_NO_MEMORY;
893 account_name = talloc_asprintf(join, "%s$", netbios_name);
894 if (!account_name) {
895 talloc_free(join);
896 r->out.error_string = NULL;
897 return NT_STATUS_NO_MEMORY;
900 /* Re-use the domain we are joining as the domain for the user
901 * to be authenticated with, unless they specified
902 * otherwise */
903 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
905 join->in.domain_name = r->in.domain_name;
906 join->in.account_name = account_name;
907 join->in.netbios_name = netbios_name;
908 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
909 join->in.acct_type = ACB_WSTRUST;
910 join->in.recreate_account = false;
911 status = libnet_JoinDomain(ctx, join, join);
912 if (!NT_STATUS_IS_OK(status)) {
913 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
914 talloc_free(join);
915 return status;
918 rep.in.domain_name = join->out.domain_name;
919 rep.in.netbios_name = netbios_name;
920 rep.in.targetdir = r->in.targetdir;
921 rep.in.domain_sid = join->out.domain_sid;
922 rep.in.realm = join->out.realm;
923 rep.in.server = join->out.samr_binding->host;
924 rep.in.join_password = join->out.join_password;
925 rep.in.kvno = join->out.kvno;
927 status = libnet_Replicate(ctx, mem_ctx, &rep);
929 r->out.domain_sid = join->out.domain_sid;
930 r->out.domain_name = join->out.domain_name;
931 r->out.error_string = rep.out.error_string;
933 return status;
938 NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
939 struct libnet_Replicate *r)
941 struct provision_store_self_join_settings *set_secrets;
942 struct libnet_BecomeDC b;
943 struct libnet_vampire_cb_state *s;
944 struct ldb_message *msg;
945 const char *error_string;
946 int ldb_ret;
947 uint32_t i;
948 NTSTATUS status;
949 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
950 const char *account_name;
951 const char *netbios_name;
953 r->out.error_string = NULL;
955 netbios_name = r->in.netbios_name;
956 account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
957 if (!account_name) {
958 talloc_free(tmp_ctx);
959 r->out.error_string = NULL;
960 return NT_STATUS_NO_MEMORY;
963 /* Re-use the domain we are joining as the domain for the user
964 * to be authenticated with, unless they specified
965 * otherwise */
966 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
968 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
969 netbios_name, r->in.domain_name, r->in.realm,
970 r->in.targetdir);
971 if (!s) {
972 return NT_STATUS_NO_MEMORY;
974 talloc_steal(s, tmp_ctx);
976 ZERO_STRUCT(b);
978 /* Be more robust:
979 * We now know the domain and realm for sure - if they didn't
980 * put one on the command line, use this for the rest of the
981 * join */
982 cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
983 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
985 /* Now set these values into the smb.conf - we probably had
986 * empty or useless defaults here from whatever smb.conf we
987 * started with */
988 lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
989 lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
991 b.in.domain_dns_name = r->in.realm;
992 b.in.domain_netbios_name = r->in.domain_name;
993 b.in.domain_sid = r->in.domain_sid;
994 b.in.source_dsa_address = r->in.server;
995 b.in.dest_dsa_netbios_name = netbios_name;
997 b.in.callbacks.private_data = s;
998 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
999 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
1000 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
1001 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
1002 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
1004 b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
1006 status = libnet_BecomeDC(ctx, s, &b);
1007 if (!NT_STATUS_IS_OK(status)) {
1008 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
1009 talloc_free(s);
1010 return status;
1013 msg = ldb_msg_new(s);
1014 if (!msg) {
1015 printf("ldb_msg_new() failed\n");
1016 talloc_free(s);
1017 return NT_STATUS_NO_MEMORY;
1019 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
1020 if (!msg->dn) {
1021 printf("ldb_msg_new(@ROOTDSE) failed\n");
1022 talloc_free(s);
1023 return NT_STATUS_NO_MEMORY;
1026 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
1027 if (ldb_ret != LDB_SUCCESS) {
1028 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
1029 talloc_free(s);
1030 return NT_STATUS_NO_MEMORY;
1033 for (i=0; i < msg->num_elements; i++) {
1034 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1037 printf("mark ROOTDSE with isSynchronized=TRUE\n");
1038 ldb_ret = ldb_modify(s->ldb, msg);
1039 if (ldb_ret != LDB_SUCCESS) {
1040 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
1041 talloc_free(s);
1042 return NT_STATUS_INTERNAL_DB_ERROR;
1044 /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
1045 * the attribute appears on the original DC after replication
1047 status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
1048 if (!NT_STATUS_IS_OK(status)) {
1049 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
1050 talloc_free(s);
1051 return status;
1053 /* prepare the transaction - this prepares to commit all the changes in
1054 the ldb from the whole vampire. Note that this
1055 triggers the writing of the linked attribute backlinks.
1057 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
1058 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
1059 return NT_STATUS_INTERNAL_DB_ERROR;
1062 set_secrets = talloc(s, struct provision_store_self_join_settings);
1063 if (!set_secrets) {
1064 r->out.error_string = NULL;
1065 talloc_free(s);
1066 return NT_STATUS_NO_MEMORY;
1069 ZERO_STRUCTP(set_secrets);
1070 set_secrets->domain_name = r->in.domain_name;
1071 set_secrets->realm = r->in.realm;
1072 set_secrets->netbios_name = netbios_name;
1073 set_secrets->secure_channel_type = SEC_CHAN_BDC;
1074 set_secrets->machine_password = r->in.join_password;
1075 set_secrets->key_version_number = r->in.kvno;
1076 set_secrets->domain_sid = r->in.domain_sid;
1078 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 r->out.error_string = talloc_steal(mem_ctx, error_string);
1081 talloc_free(s);
1082 return status;
1085 /* commit the transaction now we know the secrets were written
1086 * out properly
1088 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
1089 printf("Failed to commit vampire transaction\n");
1090 return NT_STATUS_INTERNAL_DB_ERROR;
1093 talloc_free(s);
1095 return NT_STATUS_OK;