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/>.
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 "lib/ldb/include/ldb.h"
31 #include "lib/ldb/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"
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/dom_sid.h"
43 #include "dsdb/common/util.h"
46 List of tasks vampire.py must perform:
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;
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 /* 2nd pass, with full ID->OID->name table */
72 struct dsdb_schema *self_corrected_schema;
74 /* prefixMap in LDB format, from the remote DRS server */
75 DATA_BLOB prefixmap_blob;
76 const struct dsdb_schema *schema;
78 struct ldb_context *ldb;
81 uint32_t object_count;
82 struct drsuapi_DsReplicaObjectListItemEx *first_object;
83 struct drsuapi_DsReplicaObjectListItemEx *last_object;
86 const char *targetdir;
88 struct loadparm_context *lp_ctx;
89 struct tevent_context *event_ctx;
90 unsigned total_objects;
92 const char *server_dn_str;
95 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
96 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
97 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
98 const char *netbios_name, const char *domain_name, const char *realm,
99 const char *targetdir)
101 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
107 s->event_ctx = event_ctx;
108 s->netbios_name = netbios_name;
109 s->domain_name = domain_name;
111 s->targetdir = targetdir;
115 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
117 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
121 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
123 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
124 return state->lp_ctx;
127 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
128 const struct libnet_BecomeDC_PrepareDB *p)
130 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
131 struct provision_settings settings;
132 struct provision_result result;
135 ZERO_STRUCT(settings);
136 settings.site_name = p->dest_dsa->site_name;
137 settings.root_dn_str = p->forest->root_dn_str;
138 settings.domain_dn_str = p->domain->dn_str;
139 settings.config_dn_str = p->forest->config_dn_str;
140 settings.schema_dn_str = p->forest->schema_dn_str;
141 settings.netbios_name = p->dest_dsa->netbios_name;
142 settings.realm = s->realm;
143 settings.domain = s->domain_name;
144 settings.server_dn_str = p->dest_dsa->server_dn_str;
145 settings.machine_password = generate_random_password(s, 16, 255);
146 settings.targetdir = s->targetdir;
148 status = provision_bare(s, s->lp_ctx, &settings, &result);
150 if (!NT_STATUS_IS_OK(status)) {
154 s->ldb = talloc_steal(s, result.samdb);
155 s->lp_ctx = talloc_steal(s, result.lp_ctx);
156 s->provision_schema = dsdb_get_schema(s->ldb, s);
157 s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
159 /* wrap the entire vapire operation in a transaction. This
160 isn't just cosmetic - we use this to ensure that linked
161 attribute back links are added at the end by relying on a
162 transaction commit hook in the linked attributes module. We
163 need to do this as the order of objects coming from the
164 server is not sufficiently deterministic to know that the
165 record that a backlink needs to be created in has itself
166 been created before the object containing the forward link
167 has come over the wire */
168 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
169 return NT_STATUS_FOOBAR;
177 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
178 const struct libnet_BecomeDC_CheckOptions *o)
180 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
182 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
184 o->domain->netbios_name, o->domain->dns_name));
186 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
187 o->source_dsa->dns_name, o->source_dsa->site_name));
189 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
190 "\tschema object_version[%u]\n"
191 "\tdomain behavior_version[%u]\n"
192 "\tdomain w2k3_update_revision[%u]\n",
193 o->forest->crossref_behavior_version,
194 o->forest->schema_object_version,
195 o->domain->behavior_version,
196 o->domain->w2k3_update_revision));
201 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
202 const struct libnet_BecomeDC_StoreChunk *c)
205 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
206 uint32_t object_count;
207 struct drsuapi_DsReplicaObjectListItemEx *first_object;
208 const struct drsuapi_DsReplicaObjectListItemEx *cur;
209 uint32_t linked_attributes_count;
210 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
211 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
212 struct dsdb_extended_replicated_objects *schema_objs;
213 struct repsFromTo1 *s_dsa;
215 struct ldb_context *schema_ldb;
216 struct ldb_message *msg;
217 struct ldb_message_element *prefixMap_el;
223 DEBUG(0,("Analyze and apply schema objects\n"));
225 s_dsa = talloc_zero(s, struct repsFromTo1);
226 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
227 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
228 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
230 switch (c->ctr_level) {
232 mapping_ctr = &c->ctr1->mapping_ctr;
233 object_count = s->schema_part.object_count;
234 first_object = s->schema_part.first_object;
235 linked_attributes_count = 0;
236 linked_attributes = NULL;
237 s_dsa->highwatermark = c->ctr1->new_highwatermark;
238 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
239 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
240 uptodateness_vector = NULL; /* TODO: map it */
243 mapping_ctr = &c->ctr6->mapping_ctr;
244 object_count = s->schema_part.object_count;
245 first_object = s->schema_part.first_object;
246 linked_attributes_count = c->ctr6->linked_attributes_count;
247 linked_attributes = c->ctr6->linked_attributes;
248 s_dsa->highwatermark = c->ctr6->new_highwatermark;
249 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
250 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
251 uptodateness_vector = c->ctr6->uptodateness_vector;
254 return NT_STATUS_INVALID_PARAMETER;
257 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
258 | DRSUAPI_DRS_INIT_SYNC
259 | DRSUAPI_DRS_PER_SYNC;
260 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
262 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
263 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
264 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
265 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
266 s_dsa->other_info->dns_name = tmp_dns_name;
268 schema_ldb = provision_get_schema(s, s->lp_ctx, &s->prefixmap_blob);
270 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. Will continue with local prefixMap\n"));
271 s->provision_schema = dsdb_get_schema(s->ldb, s);
273 s->provision_schema = dsdb_get_schema(schema_ldb, s);
274 ret = dsdb_reference_schema(s->ldb, s->provision_schema, false);
275 if (ret != LDB_SUCCESS) {
276 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
277 return NT_STATUS_UNSUCCESSFUL;
279 talloc_free(schema_ldb);
282 s->provision_schema->relax_OID_conversions = true;
284 /* Now convert the schema elements, using the schema we loaded locally */
285 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
286 struct dsdb_extended_replicated_object object;
287 TALLOC_CTX *tmp_ctx = talloc_new(s);
288 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
290 /* Convert the objects into LDB messages using the
291 * provision schema, and either the provision or DRS
292 * prefix map - it should not matter, as these are
293 * just schema objects, so the critical parts. At
294 * most we would mix up the mayContain etc for new
296 status = dsdb_convert_object_ex(s->ldb, s->provision_schema,
299 if (!W_ERROR_IS_OK(status)) {
300 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
302 /* Convert the schema from ldb_message format
303 * (OIDs as OID strings) into schema, using
304 * the remote prefixMap */
305 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_made_schema, object.msg);
306 if (!W_ERROR_IS_OK(status)) {
307 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
308 ldb_dn_get_linearized(object.msg->dn),
309 win_errstr(status)));
312 talloc_free(tmp_ctx);
315 /* attach the schema we just brought over DRS to the ldb, so we can use it in dsdb_convert_object_ex below */
316 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
317 if (ret != LDB_SUCCESS) {
318 DEBUG(0,("Failed to attach 1st pass schema from DRS.\n"));
319 return NT_STATUS_FOOBAR;
322 /* Now convert the schema elements again, using the schema we loaded over DRS */
323 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
324 struct dsdb_extended_replicated_object object;
325 TALLOC_CTX *tmp_ctx = talloc_new(s);
326 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
328 /* Convert the objects into LDB messages using the
329 * self_made_schema, and the DRS prefix map. We now
330 * know the full schema int->OID->name mapping, so we
331 * can get it right this time */
332 status = dsdb_convert_object_ex(s->ldb, s->self_made_schema,
335 if (!W_ERROR_IS_OK(status)) {
336 DEBUG(0,("ERROR: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
338 /* Convert the schema from ldb_message format
339 * (OIDs as OID strings) into schema, using
340 * the remote prefixMap, now that we know
341 * names for all the schema elements (from the
342 * first conversion) */
343 status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_corrected_schema, object.msg);
344 if (!W_ERROR_IS_OK(status)) {
345 DEBUG(0,("ERROR: failed to convert object %s into a schema element: %s\n",
346 ldb_dn_get_linearized(object.msg->dn),
347 win_errstr(status)));
350 talloc_free(tmp_ctx);
353 /* We don't want to use the s->self_made_schema any more */
354 s->self_made_schema = NULL;
356 /* attach the schema we just brought over DRS to the ldb */
357 ret = dsdb_set_schema(s->ldb, s->self_corrected_schema);
358 if (ret != LDB_SUCCESS) {
359 DEBUG(0,("Failed to attach 2nd pass (corrected) schema from DRS.\n"));
360 return NT_STATUS_FOOBAR;
363 /* we don't want to access the self made schema anymore */
364 s->schema = s->self_corrected_schema;
365 s->self_corrected_schema = NULL;
367 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
368 status = dsdb_extended_replicated_objects_convert(s->ldb,
373 linked_attributes_count,
379 if (!W_ERROR_IS_OK(status)) {
380 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
381 return werror_to_ntstatus(status);
384 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
385 for (i=0; i < schema_objs->num_objects; i++) {
386 struct ldb_ldif ldif;
387 fprintf(stdout, "#\n");
388 ldif.changetype = LDB_CHANGETYPE_NONE;
389 ldif.msg = schema_objs->objects[i].msg;
390 ldb_ldif_write_file(s->ldb, stdout, &ldif);
391 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
395 status = dsdb_extended_replicated_objects_commit(s->ldb, schema_objs, &seq_num);
396 if (!W_ERROR_IS_OK(status)) {
397 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
398 return werror_to_ntstatus(status);
401 msg = ldb_msg_new(schema_objs);
402 NT_STATUS_HAVE_NO_MEMORY(msg);
403 msg->dn = schema_objs->partition_dn;
405 /* We must ensure a prefixMap has been written. Unlike other
406 * attributes (including schemaInfo), it is not replicated in
407 * the normal replication stream. We can use the one from
408 * s->prefixmap_blob because we operate with one, unchanging
409 * prefixMap for this entire operation. */
410 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
411 if (ret != LDB_SUCCESS) {
412 return NT_STATUS_FOOBAR;
414 /* We want to know if a prefixMap was written already, as it
415 * would mean that the above comment was not true, and we have
416 * somehow updated the prefixMap during this transaction */
417 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
419 ret = ldb_modify(s->ldb, msg);
420 if (ret != LDB_SUCCESS) {
421 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
422 return NT_STATUS_FOOBAR;
426 talloc_free(schema_objs);
428 /* We must set these up to ensure the replMetaData is written
429 * correctly, before our NTDS Settings entry is replicated */
430 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
432 DEBUG(0,("Failed to set cached ntds invocationId\n"));
433 return NT_STATUS_FOOBAR;
435 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
437 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
438 return NT_STATUS_FOOBAR;
441 s->schema = dsdb_get_schema(s->ldb, s);
443 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
444 return NT_STATUS_FOOBAR;
450 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
451 const struct libnet_BecomeDC_StoreChunk *c)
453 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
455 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
456 uint32_t nc_object_count;
457 uint32_t object_count;
458 struct drsuapi_DsReplicaObjectListItemEx *first_object;
459 struct drsuapi_DsReplicaObjectListItemEx *cur;
460 uint32_t nc_linked_attributes_count;
461 uint32_t linked_attributes_count;
462 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
464 switch (c->ctr_level) {
466 mapping_ctr = &c->ctr1->mapping_ctr;
467 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
468 object_count = c->ctr1->object_count;
469 first_object = c->ctr1->first_object;
470 nc_linked_attributes_count = 0;
471 linked_attributes_count = 0;
472 linked_attributes = NULL;
475 mapping_ctr = &c->ctr6->mapping_ctr;
476 nc_object_count = c->ctr6->nc_object_count;
477 object_count = c->ctr6->object_count;
478 first_object = c->ctr6->first_object;
479 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
480 linked_attributes_count = c->ctr6->linked_attributes_count;
481 linked_attributes = c->ctr6->linked_attributes;
484 return NT_STATUS_INVALID_PARAMETER;
487 if (nc_object_count) {
488 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
489 c->partition->nc.dn, object_count, nc_object_count,
490 linked_attributes_count, nc_linked_attributes_count));
492 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
493 c->partition->nc.dn, object_count, linked_attributes_count));
496 if (!s->self_made_schema) {
498 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
499 /* Put the DRS prefixmap aside for the schema we are
500 * about to load in the provision, and into the one we
501 * are making with the help of DRS */
503 mapping_ctr_without_schema_info = *mapping_ctr;
505 /* This strips off the 0xFF schema info from the end,
506 * because we don't want it in the blob */
507 if (mapping_ctr_without_schema_info.num_mappings > 0) {
508 mapping_ctr_without_schema_info.num_mappings--;
510 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
511 if (!W_ERROR_IS_OK(werr)) {
512 return werror_to_ntstatus(werr);
515 /* Set up two manually-constructed schema - the local
516 * schema from the provision will be used to build
517 * one, which will then in turn be used to build the
519 s->self_made_schema = dsdb_new_schema(s);
520 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
521 s->self_corrected_schema = dsdb_new_schema(s);
522 NT_STATUS_HAVE_NO_MEMORY(s->self_corrected_schema);
524 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
525 if (!W_ERROR_IS_OK(status)) {
526 return werror_to_ntstatus(status);
529 status = dsdb_load_prefixmap_from_drsuapi(s->self_corrected_schema, mapping_ctr);
530 if (!W_ERROR_IS_OK(status)) {
531 return werror_to_ntstatus(status);
534 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
535 if (!W_ERROR_IS_OK(status)) {
536 return werror_to_ntstatus(status);
540 if (!s->schema_part.first_object) {
541 s->schema_part.object_count = object_count;
542 s->schema_part.first_object = talloc_steal(s, first_object);
544 s->schema_part.object_count += object_count;
545 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
548 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
549 s->schema_part.last_object = cur;
551 if (!c->partition->more_data) {
552 return libnet_vampire_cb_apply_schema(s, c);
558 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
559 const struct libnet_BecomeDC_StoreChunk *c)
561 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
563 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
564 uint32_t nc_object_count;
565 uint32_t object_count;
566 struct drsuapi_DsReplicaObjectListItemEx *first_object;
567 uint32_t nc_linked_attributes_count;
568 uint32_t linked_attributes_count;
569 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
570 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
571 struct dsdb_extended_replicated_objects *objs;
572 struct repsFromTo1 *s_dsa;
577 s_dsa = talloc_zero(s, struct repsFromTo1);
578 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
579 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
580 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
582 switch (c->ctr_level) {
584 mapping_ctr = &c->ctr1->mapping_ctr;
585 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
586 object_count = c->ctr1->object_count;
587 first_object = c->ctr1->first_object;
588 nc_linked_attributes_count = 0;
589 linked_attributes_count = 0;
590 linked_attributes = NULL;
591 s_dsa->highwatermark = c->ctr1->new_highwatermark;
592 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
593 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
594 uptodateness_vector = NULL; /* TODO: map it */
597 mapping_ctr = &c->ctr6->mapping_ctr;
598 nc_object_count = c->ctr6->nc_object_count;
599 object_count = c->ctr6->object_count;
600 first_object = c->ctr6->first_object;
601 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
602 linked_attributes_count = c->ctr6->linked_attributes_count;
603 linked_attributes = c->ctr6->linked_attributes;
604 s_dsa->highwatermark = c->ctr6->new_highwatermark;
605 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
606 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
607 uptodateness_vector = c->ctr6->uptodateness_vector;
610 return NT_STATUS_INVALID_PARAMETER;
613 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
614 | DRSUAPI_DRS_INIT_SYNC
615 | DRSUAPI_DRS_PER_SYNC;
616 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
618 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
619 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
620 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
621 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
622 s_dsa->other_info->dns_name = tmp_dns_name;
624 /* we want to show a count per partition */
625 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
626 s->total_objects = 0;
627 talloc_free(s->last_partition);
628 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
630 s->total_objects += object_count;
632 if (nc_object_count) {
633 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
634 c->partition->nc.dn, s->total_objects, nc_object_count,
635 linked_attributes_count, nc_linked_attributes_count));
637 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
638 c->partition->nc.dn, s->total_objects, linked_attributes_count));
642 status = dsdb_extended_replicated_objects_convert(s->ldb,
647 linked_attributes_count,
653 if (!W_ERROR_IS_OK(status)) {
654 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
655 return werror_to_ntstatus(status);
658 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
659 for (i=0; i < objs->num_objects; i++) {
660 struct ldb_ldif ldif;
661 fprintf(stdout, "#\n");
662 ldif.changetype = LDB_CHANGETYPE_NONE;
663 ldif.msg = objs->objects[i].msg;
664 ldb_ldif_write_file(s->ldb, stdout, &ldif);
665 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
668 status = dsdb_extended_replicated_objects_commit(s->ldb,
670 if (!W_ERROR_IS_OK(status)) {
671 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
672 return werror_to_ntstatus(status);
678 for (i=0; i < linked_attributes_count; i++) {
679 const struct dsdb_attribute *sa;
681 if (!linked_attributes[i].identifier) {
682 return NT_STATUS_FOOBAR;
685 if (!linked_attributes[i].value.blob) {
686 return NT_STATUS_FOOBAR;
689 sa = dsdb_attribute_by_attributeID_id(s->schema,
690 linked_attributes[i].attid);
692 return NT_STATUS_FOOBAR;
695 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
696 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
697 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
699 linked_attributes[i].value.blob->data,
700 linked_attributes[i].value.blob->length);
707 static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
708 struct ldb_context *ldb,
709 const char *server_dn_str,
710 const char *netbios_name,
714 struct ldb_message *msg;
715 struct ldb_message_element *el;
716 struct ldb_dn *server_dn;
717 const char *dNSHostName = strlower_talloc(mem_ctx,
718 talloc_asprintf(mem_ctx,
722 msg = ldb_msg_new(mem_ctx);
724 return NT_STATUS_NO_MEMORY;
727 server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
729 return NT_STATUS_INTERNAL_ERROR;
733 ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
734 if (ret != LDB_SUCCESS) {
735 return NT_STATUS_INTERNAL_ERROR;
738 ret = ldb_msg_add_steal_string(msg,
740 talloc_asprintf(el->values, "%s", dNSHostName));
741 if (ret != LDB_SUCCESS) {
742 return NT_STATUS_INTERNAL_ERROR;
745 ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
746 if (ret != LDB_SUCCESS) {
747 DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
748 ldb_errstring(ldb)));
749 return NT_STATUS_INTERNAL_ERROR;
756 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
757 struct libnet_Vampire *r)
759 struct libnet_JoinDomain *join;
760 struct libnet_Replicate rep;
763 const char *account_name;
764 const char *netbios_name;
766 r->out.error_string = NULL;
768 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
770 return NT_STATUS_NO_MEMORY;
773 if (r->in.netbios_name != NULL) {
774 netbios_name = r->in.netbios_name;
776 netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
779 r->out.error_string = NULL;
780 return NT_STATUS_NO_MEMORY;
784 account_name = talloc_asprintf(join, "%s$", netbios_name);
787 r->out.error_string = NULL;
788 return NT_STATUS_NO_MEMORY;
791 /* Re-use the domain we are joining as the domain for the user
792 * to be authenticated with, unless they specified
794 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
796 join->in.domain_name = r->in.domain_name;
797 join->in.account_name = account_name;
798 join->in.netbios_name = netbios_name;
799 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
800 join->in.acct_type = ACB_WSTRUST;
801 join->in.recreate_account = false;
802 status = libnet_JoinDomain(ctx, join, join);
803 if (!NT_STATUS_IS_OK(status)) {
804 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
809 rep.in.domain_name = join->out.domain_name;
810 rep.in.netbios_name = netbios_name;
811 rep.in.targetdir = r->in.targetdir;
812 rep.in.domain_sid = join->out.domain_sid;
813 rep.in.realm = join->out.realm;
814 rep.in.server = join->out.samr_binding->host;
815 rep.in.join_password = join->out.join_password;
816 rep.in.kvno = join->out.kvno;
818 status = libnet_Replicate(ctx, mem_ctx, &rep);
820 r->out.domain_sid = join->out.domain_sid;
821 r->out.domain_name = join->out.domain_name;
822 r->out.error_string = rep.out.error_string;
829 NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
830 struct libnet_Replicate *r)
832 struct provision_store_self_join_settings *set_secrets;
833 struct libnet_BecomeDC b;
834 struct libnet_vampire_cb_state *s;
835 struct ldb_message *msg;
836 const char *error_string;
840 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
841 const char *account_name;
842 const char *netbios_name;
844 r->out.error_string = NULL;
846 netbios_name = r->in.netbios_name;
847 account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
849 talloc_free(tmp_ctx);
850 r->out.error_string = NULL;
851 return NT_STATUS_NO_MEMORY;
854 /* Re-use the domain we are joining as the domain for the user
855 * to be authenticated with, unless they specified
857 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
859 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
860 netbios_name, r->in.domain_name, r->in.realm,
863 return NT_STATUS_NO_MEMORY;
865 talloc_steal(s, tmp_ctx);
870 * We now know the domain and realm for sure - if they didn't
871 * put one on the command line, use this for the rest of the
873 cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
874 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
876 /* Now set these values into the smb.conf - we probably had
877 * empty or useless defaults here from whatever smb.conf we
879 lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
880 lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
882 b.in.domain_dns_name = r->in.realm;
883 b.in.domain_netbios_name = r->in.domain_name;
884 b.in.domain_sid = r->in.domain_sid;
885 b.in.source_dsa_address = r->in.server;
886 b.in.dest_dsa_netbios_name = netbios_name;
888 b.in.callbacks.private_data = s;
889 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
890 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
891 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
892 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
893 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
895 b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
897 status = libnet_BecomeDC(ctx, s, &b);
898 if (!NT_STATUS_IS_OK(status)) {
899 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
904 msg = ldb_msg_new(s);
906 printf("ldb_msg_new() failed\n");
908 return NT_STATUS_NO_MEMORY;
910 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
912 printf("ldb_msg_new(@ROOTDSE) failed\n");
914 return NT_STATUS_NO_MEMORY;
917 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
918 if (ldb_ret != LDB_SUCCESS) {
919 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
921 return NT_STATUS_NO_MEMORY;
924 for (i=0; i < msg->num_elements; i++) {
925 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
928 printf("mark ROOTDSE with isSynchronized=TRUE\n");
929 ldb_ret = ldb_modify(s->ldb, msg);
930 if (ldb_ret != LDB_SUCCESS) {
931 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
933 return NT_STATUS_INTERNAL_DB_ERROR;
935 /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
936 * the attribute appears on the original DC after replication
938 status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
939 if (!NT_STATUS_IS_OK(status)) {
940 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
944 /* prepare the transaction - this prepares to commit all the changes in
945 the ldb from the whole vampire. Note that this
946 triggers the writing of the linked attribute backlinks.
948 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
949 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
950 return NT_STATUS_INTERNAL_DB_ERROR;
953 set_secrets = talloc(s, struct provision_store_self_join_settings);
955 r->out.error_string = NULL;
957 return NT_STATUS_NO_MEMORY;
960 ZERO_STRUCTP(set_secrets);
961 set_secrets->domain_name = r->in.domain_name;
962 set_secrets->realm = r->in.realm;
963 set_secrets->netbios_name = netbios_name;
964 set_secrets->secure_channel_type = SEC_CHAN_BDC;
965 set_secrets->machine_password = r->in.join_password;
966 set_secrets->key_version_number = r->in.kvno;
967 set_secrets->domain_sid = r->in.domain_sid;
969 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
970 if (!NT_STATUS_IS_OK(status)) {
971 r->out.error_string = talloc_steal(mem_ctx, error_string);
976 /* commit the transaction now we know the secrets were written
979 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
980 printf("Failed to commit vampire transaction\n");
981 return NT_STATUS_INTERNAL_DB_ERROR;