dns: The QCLASS is called IN, not IP
[Samba/gebeck_regimport.git] / source4 / libnet / libnet_vampire.c
blobefbcd8af6814c963f48f18546975fb68e6a5a4ba
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;
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;
292 status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
293 s, &pfm_remote, NULL);
294 if (!W_ERROR_IS_OK(status)) {
295 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
296 win_errstr(status)));
297 return werror_to_ntstatus(status);
300 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
301 | DRSUAPI_DRS_INIT_SYNC
302 | DRSUAPI_DRS_PER_SYNC;
303 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
305 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
306 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
307 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
308 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
309 s_dsa->other_info->dns_name = tmp_dns_name;
311 schema_ldb = provision_get_schema(s, s->lp_ctx, &s->prefixmap_blob);
312 if (!schema_ldb) {
313 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
314 "Will continue with local prefixMap\n"));
315 provision_schema = dsdb_get_schema(s->ldb, s);
316 } else {
317 provision_schema = dsdb_get_schema(schema_ldb, s);
318 ret = dsdb_reference_schema(s->ldb, provision_schema, false);
319 if (ret != LDB_SUCCESS) {
320 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
321 return NT_STATUS_UNSUCCESSFUL;
323 talloc_free(schema_ldb);
326 /* create a list of objects yet to be converted */
327 for (cur = first_object; cur; cur = cur->next_object) {
328 schema_list_item = talloc(s, struct schema_list);
329 schema_list_item->obj = cur;
330 DLIST_ADD_END(schema_list, schema_list_item, struct schema_list);
333 /* resolve objects until all are resolved and in local schema */
334 pass_no = 1;
335 working_schema = provision_schema;
337 while (schema_list) {
338 uint32_t converted_obj_count = 0;
339 uint32_t failed_obj_count = 0;
340 TALLOC_CTX *tmp_ctx = talloc_new(s);
341 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
343 for (schema_list_item = schema_list; schema_list_item; schema_list_item=schema_list_next_item) {
344 struct dsdb_extended_replicated_object object;
346 cur = schema_list_item->obj;
348 /* Save the next item, now we have saved out
349 * the current one, so we can DLIST_REMOVE it
350 * safely */
351 schema_list_next_item = schema_list_item->next;
354 * Convert the objects into LDB messages using the
355 * schema we have so far. It's ok if we fail to convert
356 * an object. We should convert more objects on next pass.
358 status = dsdb_convert_object_ex(s->ldb, working_schema, pfm_remote,
359 cur, c->gensec_skey,
360 ignore_attids,
361 tmp_ctx, &object);
362 if (!W_ERROR_IS_OK(status)) {
363 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n",
364 cur->object.identifier->dn));
366 failed_obj_count++;
367 } else {
369 * Convert the schema from ldb_message format
370 * (OIDs as OID strings) into schema, using
371 * the remote prefixMap
373 status = dsdb_schema_set_el_from_ldb_msg(s->ldb,
374 s->self_made_schema,
375 object.msg);
376 if (!W_ERROR_IS_OK(status)) {
377 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
378 ldb_dn_get_linearized(object.msg->dn),
379 win_errstr(status)));
380 failed_obj_count++;
381 } else {
382 DLIST_REMOVE(schema_list, schema_list_item);
383 converted_obj_count++;
387 talloc_free(tmp_ctx);
389 DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n",
390 pass_no, failed_obj_count, converted_obj_count, object_count));
391 pass_no++;
393 /* check if we converted any objects in this pass */
394 if (converted_obj_count == 0) {
395 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));
396 return NT_STATUS_INTERNAL_ERROR;
399 if (schema_list) {
400 /* prepare for another cycle */
401 working_schema = s->self_made_schema;
403 ret = dsdb_setup_sorted_accessors(s->ldb, working_schema);
404 if (LDB_SUCCESS != ret) {
405 DEBUG(0,("Failed to create schema-cache indexes!\n"));
406 return NT_STATUS_INTERNAL_ERROR;
411 /* free temp objects for 1st conversion phase */
412 talloc_unlink(s, provision_schema);
413 TALLOC_FREE(schema_list);
416 * attach the schema we just brought over DRS to the ldb,
417 * so we can use it in dsdb_convert_object_ex below
419 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
420 if (ret != LDB_SUCCESS) {
421 DEBUG(0,("Failed to attach working schema from DRS.\n"));
422 return NT_STATUS_FOOBAR;
425 /* we don't want to access the self made schema anymore */
426 s->schema = s->self_made_schema;
427 s->self_made_schema = NULL;
429 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
430 status = dsdb_replicated_objects_convert(s->ldb,
431 s->schema,
432 c->partition->nc.dn,
433 mapping_ctr,
434 object_count,
435 first_object,
436 linked_attributes_count,
437 linked_attributes,
438 s_dsa,
439 uptodateness_vector,
440 c->gensec_skey,
441 s, &schema_objs);
442 if (!W_ERROR_IS_OK(status)) {
443 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
444 return werror_to_ntstatus(status);
447 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
448 for (i=0; i < schema_objs->num_objects; i++) {
449 struct ldb_ldif ldif;
450 fprintf(stdout, "#\n");
451 ldif.changetype = LDB_CHANGETYPE_NONE;
452 ldif.msg = schema_objs->objects[i].msg;
453 ldb_ldif_write_file(s->ldb, stdout, &ldif);
454 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
458 status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
459 if (!W_ERROR_IS_OK(status)) {
460 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
461 return werror_to_ntstatus(status);
464 msg = ldb_msg_new(schema_objs);
465 NT_STATUS_HAVE_NO_MEMORY(msg);
466 msg->dn = schema_objs->partition_dn;
468 /* We must ensure a prefixMap has been written. Unlike other
469 * attributes (including schemaInfo), it is not replicated in
470 * the normal replication stream. We can use the one from
471 * s->prefixmap_blob because we operate with one, unchanging
472 * prefixMap for this entire operation. */
473 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
474 if (ret != LDB_SUCCESS) {
475 return NT_STATUS_FOOBAR;
477 /* We want to know if a prefixMap was written already, as it
478 * would mean that the above comment was not true, and we have
479 * somehow updated the prefixMap during this transaction */
480 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
482 ret = ldb_modify(s->ldb, msg);
483 if (ret != LDB_SUCCESS) {
484 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
485 return NT_STATUS_FOOBAR;
488 talloc_free(s_dsa);
489 talloc_free(schema_objs);
491 /* We must set these up to ensure the replMetaData is written
492 * correctly, before our NTDS Settings entry is replicated */
493 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
494 if (!ok) {
495 DEBUG(0,("Failed to set cached ntds invocationId\n"));
496 return NT_STATUS_FOOBAR;
498 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
499 if (!ok) {
500 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
501 return NT_STATUS_FOOBAR;
504 s->schema = dsdb_get_schema(s->ldb, s);
505 if (!s->schema) {
506 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
507 return NT_STATUS_FOOBAR;
510 return NT_STATUS_OK;
513 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
514 const struct libnet_BecomeDC_StoreChunk *c)
516 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
517 WERROR status;
518 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
519 uint32_t nc_object_count;
520 uint32_t object_count;
521 struct drsuapi_DsReplicaObjectListItemEx *first_object;
522 struct drsuapi_DsReplicaObjectListItemEx *cur;
523 uint32_t nc_linked_attributes_count;
524 uint32_t linked_attributes_count;
525 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
527 switch (c->ctr_level) {
528 case 1:
529 mapping_ctr = &c->ctr1->mapping_ctr;
530 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
531 object_count = c->ctr1->object_count;
532 first_object = c->ctr1->first_object;
533 nc_linked_attributes_count = 0;
534 linked_attributes_count = 0;
535 linked_attributes = NULL;
536 break;
537 case 6:
538 mapping_ctr = &c->ctr6->mapping_ctr;
539 nc_object_count = c->ctr6->nc_object_count;
540 object_count = c->ctr6->object_count;
541 first_object = c->ctr6->first_object;
542 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
543 linked_attributes_count = c->ctr6->linked_attributes_count;
544 linked_attributes = c->ctr6->linked_attributes;
545 break;
546 default:
547 return NT_STATUS_INVALID_PARAMETER;
550 if (nc_object_count) {
551 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
552 c->partition->nc.dn, object_count, nc_object_count,
553 linked_attributes_count, nc_linked_attributes_count));
554 } else {
555 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
556 c->partition->nc.dn, object_count, linked_attributes_count));
559 if (!s->self_made_schema) {
560 WERROR werr;
561 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
562 /* Put the DRS prefixmap aside for the schema we are
563 * about to load in the provision, and into the one we
564 * are making with the help of DRS */
566 mapping_ctr_without_schema_info = *mapping_ctr;
568 /* This strips off the 0xFF schema info from the end,
569 * because we don't want it in the blob */
570 if (mapping_ctr_without_schema_info.num_mappings > 0) {
571 mapping_ctr_without_schema_info.num_mappings--;
573 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
574 if (!W_ERROR_IS_OK(werr)) {
575 return werror_to_ntstatus(werr);
578 /* Set up two manually-constructed schema - the local
579 * schema from the provision will be used to build
580 * one, which will then in turn be used to build the
581 * other. */
582 s->self_made_schema = dsdb_new_schema(s);
583 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
585 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
586 if (!W_ERROR_IS_OK(status)) {
587 return werror_to_ntstatus(status);
589 } else {
590 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
591 if (!W_ERROR_IS_OK(status)) {
592 return werror_to_ntstatus(status);
596 if (!s->schema_part.first_object) {
597 s->schema_part.object_count = object_count;
598 s->schema_part.first_object = talloc_steal(s, first_object);
599 } else {
600 s->schema_part.object_count += object_count;
601 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
602 first_object);
604 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
605 s->schema_part.last_object = cur;
607 if (!c->partition->more_data) {
608 return libnet_vampire_cb_apply_schema(s, c);
611 return NT_STATUS_OK;
614 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
615 const struct libnet_BecomeDC_StoreChunk *c)
617 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
618 WERROR status;
619 struct dsdb_schema *schema;
620 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
621 uint32_t nc_object_count;
622 uint32_t object_count;
623 struct drsuapi_DsReplicaObjectListItemEx *first_object;
624 uint32_t nc_linked_attributes_count;
625 uint32_t linked_attributes_count;
626 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
627 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
628 struct dsdb_extended_replicated_objects *objs;
629 uint32_t req_replica_flags;
630 struct repsFromTo1 *s_dsa;
631 char *tmp_dns_name;
632 uint32_t i;
633 uint64_t seq_num;
635 s_dsa = talloc_zero(s, struct repsFromTo1);
636 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
637 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
638 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
640 switch (c->ctr_level) {
641 case 1:
642 mapping_ctr = &c->ctr1->mapping_ctr;
643 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
644 object_count = c->ctr1->object_count;
645 first_object = c->ctr1->first_object;
646 nc_linked_attributes_count = 0;
647 linked_attributes_count = 0;
648 linked_attributes = NULL;
649 s_dsa->highwatermark = c->ctr1->new_highwatermark;
650 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
651 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
652 uptodateness_vector = NULL; /* TODO: map it */
653 break;
654 case 6:
655 mapping_ctr = &c->ctr6->mapping_ctr;
656 nc_object_count = c->ctr6->nc_object_count;
657 object_count = c->ctr6->object_count;
658 first_object = c->ctr6->first_object;
659 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
660 linked_attributes_count = c->ctr6->linked_attributes_count;
661 linked_attributes = c->ctr6->linked_attributes;
662 s_dsa->highwatermark = c->ctr6->new_highwatermark;
663 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
664 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
665 uptodateness_vector = c->ctr6->uptodateness_vector;
666 break;
667 default:
668 return NT_STATUS_INVALID_PARAMETER;
671 switch (c->req_level) {
672 case 0:
673 /* none */
674 req_replica_flags = 0;
675 break;
676 case 5:
677 req_replica_flags = c->req5->replica_flags;
678 break;
679 case 8:
680 req_replica_flags = c->req8->replica_flags;
681 break;
682 case 10:
683 req_replica_flags = c->req10->replica_flags;
684 break;
685 default:
686 return NT_STATUS_INVALID_PARAMETER;
689 if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
691 * If we only replicate the critical objects
692 * we should not remember what we already
693 * got, as it is incomplete.
695 ZERO_STRUCT(s_dsa->highwatermark);
696 uptodateness_vector = NULL;
699 /* TODO: avoid hardcoded flags */
700 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
701 | DRSUAPI_DRS_INIT_SYNC
702 | DRSUAPI_DRS_PER_SYNC;
703 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
705 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
706 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
707 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
708 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
709 s_dsa->other_info->dns_name = tmp_dns_name;
711 /* we want to show a count per partition */
712 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
713 s->total_objects = 0;
714 talloc_free(s->last_partition);
715 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
717 s->total_objects += object_count;
719 if (nc_object_count) {
720 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
721 c->partition->nc.dn, s->total_objects, nc_object_count,
722 linked_attributes_count, nc_linked_attributes_count));
723 } else {
724 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
725 c->partition->nc.dn, s->total_objects, linked_attributes_count));
729 schema = dsdb_get_schema(s->ldb, NULL);
730 if (!schema) {
731 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
732 return NT_STATUS_INTERNAL_ERROR;
735 status = dsdb_replicated_objects_convert(s->ldb,
736 schema,
737 c->partition->nc.dn,
738 mapping_ctr,
739 object_count,
740 first_object,
741 linked_attributes_count,
742 linked_attributes,
743 s_dsa,
744 uptodateness_vector,
745 c->gensec_skey,
746 s, &objs);
747 if (!W_ERROR_IS_OK(status)) {
748 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
749 return werror_to_ntstatus(status);
752 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
753 for (i=0; i < objs->num_objects; i++) {
754 struct ldb_ldif ldif;
755 fprintf(stdout, "#\n");
756 ldif.changetype = LDB_CHANGETYPE_NONE;
757 ldif.msg = objs->objects[i].msg;
758 ldb_ldif_write_file(s->ldb, stdout, &ldif);
759 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
762 status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
763 if (!W_ERROR_IS_OK(status)) {
764 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
765 return werror_to_ntstatus(status);
768 talloc_free(s_dsa);
769 talloc_free(objs);
771 for (i=0; i < linked_attributes_count; i++) {
772 const struct dsdb_attribute *sa;
774 if (!linked_attributes[i].identifier) {
775 return NT_STATUS_FOOBAR;
778 if (!linked_attributes[i].value.blob) {
779 return NT_STATUS_FOOBAR;
782 sa = dsdb_attribute_by_attributeID_id(s->schema,
783 linked_attributes[i].attid);
784 if (!sa) {
785 return NT_STATUS_FOOBAR;
788 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
789 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
790 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
791 dump_data(0,
792 linked_attributes[i].value.blob->data,
793 linked_attributes[i].value.blob->length);
797 return NT_STATUS_OK;
800 static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
801 struct ldb_context *ldb,
802 const char *server_dn_str,
803 const char *netbios_name,
804 const char *realm)
806 int ret;
807 struct ldb_message *msg;
808 struct ldb_message_element *el;
809 struct ldb_dn *server_dn;
810 const char *dNSHostName = strlower_talloc(mem_ctx,
811 talloc_asprintf(mem_ctx,
812 "%s.%s",
813 netbios_name,
814 realm));
815 msg = ldb_msg_new(mem_ctx);
816 if (msg == NULL) {
817 return NT_STATUS_NO_MEMORY;
820 server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
821 if (!server_dn) {
822 return NT_STATUS_INTERNAL_ERROR;
825 msg->dn = server_dn;
826 ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
827 if (ret != LDB_SUCCESS) {
828 return NT_STATUS_INTERNAL_ERROR;
831 ret = ldb_msg_add_steal_string(msg,
832 "dNSHostName",
833 talloc_asprintf(el->values, "%s", dNSHostName));
834 if (ret != LDB_SUCCESS) {
835 return NT_STATUS_INTERNAL_ERROR;
838 ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
839 if (ret != LDB_SUCCESS) {
840 DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
841 ldb_errstring(ldb)));
842 return NT_STATUS_INTERNAL_ERROR;
845 return NT_STATUS_OK;
849 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
850 struct libnet_Vampire *r)
852 struct libnet_JoinDomain *join;
853 struct libnet_Replicate rep;
854 NTSTATUS status;
856 const char *account_name;
857 const char *netbios_name;
859 r->out.error_string = NULL;
861 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
862 if (!join) {
863 return NT_STATUS_NO_MEMORY;
866 if (r->in.netbios_name != NULL) {
867 netbios_name = r->in.netbios_name;
868 } else {
869 netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
870 if (!netbios_name) {
871 talloc_free(join);
872 r->out.error_string = NULL;
873 return NT_STATUS_NO_MEMORY;
877 account_name = talloc_asprintf(join, "%s$", netbios_name);
878 if (!account_name) {
879 talloc_free(join);
880 r->out.error_string = NULL;
881 return NT_STATUS_NO_MEMORY;
884 /* Re-use the domain we are joining as the domain for the user
885 * to be authenticated with, unless they specified
886 * otherwise */
887 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
889 join->in.domain_name = r->in.domain_name;
890 join->in.account_name = account_name;
891 join->in.netbios_name = netbios_name;
892 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
893 join->in.acct_type = ACB_WSTRUST;
894 join->in.recreate_account = false;
895 status = libnet_JoinDomain(ctx, join, join);
896 if (!NT_STATUS_IS_OK(status)) {
897 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
898 talloc_free(join);
899 return status;
902 rep.in.domain_name = join->out.domain_name;
903 rep.in.netbios_name = netbios_name;
904 rep.in.targetdir = r->in.targetdir;
905 rep.in.domain_sid = join->out.domain_sid;
906 rep.in.realm = join->out.realm;
907 rep.in.server = join->out.samr_binding->host;
908 rep.in.join_password = join->out.join_password;
909 rep.in.kvno = join->out.kvno;
911 status = libnet_Replicate(ctx, mem_ctx, &rep);
913 r->out.domain_sid = join->out.domain_sid;
914 r->out.domain_name = join->out.domain_name;
915 r->out.error_string = rep.out.error_string;
917 return status;
922 NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
923 struct libnet_Replicate *r)
925 struct provision_store_self_join_settings *set_secrets;
926 struct libnet_BecomeDC b;
927 struct libnet_vampire_cb_state *s;
928 struct ldb_message *msg;
929 const char *error_string;
930 int ldb_ret;
931 uint32_t i;
932 NTSTATUS status;
933 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
934 const char *account_name;
935 const char *netbios_name;
937 r->out.error_string = NULL;
939 netbios_name = r->in.netbios_name;
940 account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
941 if (!account_name) {
942 talloc_free(tmp_ctx);
943 r->out.error_string = NULL;
944 return NT_STATUS_NO_MEMORY;
947 /* Re-use the domain we are joining as the domain for the user
948 * to be authenticated with, unless they specified
949 * otherwise */
950 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
952 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
953 netbios_name, r->in.domain_name, r->in.realm,
954 r->in.targetdir);
955 if (!s) {
956 return NT_STATUS_NO_MEMORY;
958 talloc_steal(s, tmp_ctx);
960 ZERO_STRUCT(b);
962 /* Be more robust:
963 * We now know the domain and realm for sure - if they didn't
964 * put one on the command line, use this for the rest of the
965 * join */
966 cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
967 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
969 /* Now set these values into the smb.conf - we probably had
970 * empty or useless defaults here from whatever smb.conf we
971 * started with */
972 lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
973 lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
975 b.in.domain_dns_name = r->in.realm;
976 b.in.domain_netbios_name = r->in.domain_name;
977 b.in.domain_sid = r->in.domain_sid;
978 b.in.source_dsa_address = r->in.server;
979 b.in.dest_dsa_netbios_name = netbios_name;
981 b.in.callbacks.private_data = s;
982 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
983 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
984 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
985 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
986 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
988 b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
990 status = libnet_BecomeDC(ctx, s, &b);
991 if (!NT_STATUS_IS_OK(status)) {
992 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
993 talloc_free(s);
994 return status;
997 msg = ldb_msg_new(s);
998 if (!msg) {
999 printf("ldb_msg_new() failed\n");
1000 talloc_free(s);
1001 return NT_STATUS_NO_MEMORY;
1003 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
1004 if (!msg->dn) {
1005 printf("ldb_msg_new(@ROOTDSE) failed\n");
1006 talloc_free(s);
1007 return NT_STATUS_NO_MEMORY;
1010 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
1011 if (ldb_ret != LDB_SUCCESS) {
1012 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
1013 talloc_free(s);
1014 return NT_STATUS_NO_MEMORY;
1017 for (i=0; i < msg->num_elements; i++) {
1018 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1021 printf("mark ROOTDSE with isSynchronized=TRUE\n");
1022 ldb_ret = ldb_modify(s->ldb, msg);
1023 if (ldb_ret != LDB_SUCCESS) {
1024 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
1025 talloc_free(s);
1026 return NT_STATUS_INTERNAL_DB_ERROR;
1028 /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
1029 * the attribute appears on the original DC after replication
1031 status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
1034 talloc_free(s);
1035 return status;
1037 /* prepare the transaction - this prepares to commit all the changes in
1038 the ldb from the whole vampire. Note that this
1039 triggers the writing of the linked attribute backlinks.
1041 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
1042 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
1043 return NT_STATUS_INTERNAL_DB_ERROR;
1046 set_secrets = talloc(s, struct provision_store_self_join_settings);
1047 if (!set_secrets) {
1048 r->out.error_string = NULL;
1049 talloc_free(s);
1050 return NT_STATUS_NO_MEMORY;
1053 ZERO_STRUCTP(set_secrets);
1054 set_secrets->domain_name = r->in.domain_name;
1055 set_secrets->realm = r->in.realm;
1056 set_secrets->netbios_name = netbios_name;
1057 set_secrets->secure_channel_type = SEC_CHAN_BDC;
1058 set_secrets->machine_password = r->in.join_password;
1059 set_secrets->key_version_number = r->in.kvno;
1060 set_secrets->domain_sid = r->in.domain_sid;
1062 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 r->out.error_string = talloc_steal(mem_ctx, error_string);
1065 talloc_free(s);
1066 return status;
1069 /* commit the transaction now we know the secrets were written
1070 * out properly
1072 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
1073 printf("Failed to commit vampire transaction\n");
1074 return NT_STATUS_INTERNAL_DB_ERROR;
1077 talloc_free(s);
1079 return NT_STATUS_OK;