s3:libsmb: let cli_np_tstream use smb1cli_trans
[Samba.git] / source4 / libnet / libnet_vampire.c
blob9489f0bccb0151f24bbbfcef528733314fe035e6
1 /*
2 Unix SMB/CIFS implementation.
4 Extract the user/system database from a remote server
6 Copyright (C) Stefan Metzmacher 2004-2006
7 Copyright (C) Brad Henry 2005
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "libnet/libnet.h"
27 #include "lib/events/events.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/dlinklist.h"
30 #include <ldb.h>
31 #include <ldb_errors.h>
32 #include "librpc/ndr/libndr.h"
33 #include "librpc/gen_ndr/ndr_drsuapi.h"
34 #include "librpc/gen_ndr/ndr_drsblobs.h"
35 #include "librpc/gen_ndr/ndr_misc.h"
36 #include "system/time.h"
37 #include "ldb_wrap.h"
38 #include "auth/auth.h"
39 #include "auth/credentials/credentials.h"
40 #include "param/param.h"
41 #include "param/provision.h"
42 #include "libcli/security/security.h"
43 #include "dsdb/common/util.h"
45 /*
46 List of tasks vampire.py must perform:
47 - Domain Join
48 - but don't write the secrets.ldb
49 - results for this should be enough to handle the provision
50 - if vampire method is samsync
51 - Provision using these results
52 - do we still want to support this NT4 technology?
53 - Start samsync with libnet code
54 - provision in the callback
55 - Write out the secrets database, using the code from libnet_Join
58 struct libnet_vampire_cb_state {
59 const char *netbios_name;
60 const char *domain_name;
61 const char *realm;
62 struct cli_credentials *machine_account;
64 /* Schema loaded from local LDIF files */
65 struct dsdb_schema *provision_schema;
67 /* 1st pass, with some OIDs/attribute names/class names not
68 * converted, because we may not know them yet */
69 struct dsdb_schema *self_made_schema;
71 /* prefixMap in LDB format, from the remote DRS server */
72 DATA_BLOB prefixmap_blob;
73 const struct dsdb_schema *schema;
75 struct ldb_context *ldb;
77 struct {
78 uint32_t object_count;
79 struct drsuapi_DsReplicaObjectListItemEx *first_object;
80 struct drsuapi_DsReplicaObjectListItemEx *last_object;
81 } schema_part;
83 const char *targetdir;
85 struct loadparm_context *lp_ctx;
86 struct tevent_context *event_ctx;
87 unsigned total_objects;
88 char *last_partition;
89 const char *server_dn_str;
92 /* initialise a state structure ready for replication of chunks */
93 void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
94 struct ldb_context *samdb,
95 struct loadparm_context *lp_ctx)
97 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
98 if (!s) {
99 return NULL;
102 s->ldb = samdb;
103 s->lp_ctx = lp_ctx;
104 s->provision_schema = dsdb_get_schema(s->ldb, s);
105 s->schema = s->provision_schema;
106 s->netbios_name = lpcfg_netbios_name(lp_ctx);
107 s->domain_name = lpcfg_workgroup(lp_ctx);
108 s->realm = lpcfg_realm(lp_ctx);
110 return s;
113 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
114 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
115 struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
116 const char *netbios_name, const char *domain_name, const char *realm,
117 const char *targetdir)
119 struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
120 if (!s) {
121 return NULL;
124 s->lp_ctx = lp_ctx;
125 s->event_ctx = event_ctx;
126 s->netbios_name = netbios_name;
127 s->domain_name = domain_name;
128 s->realm = realm;
129 s->targetdir = targetdir;
130 return s;
133 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
135 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
136 return state->ldb;
139 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
141 state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
142 return state->lp_ctx;
145 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
146 const struct libnet_BecomeDC_PrepareDB *p)
148 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
149 struct provision_settings settings;
150 struct provision_result result;
151 NTSTATUS status;
153 ZERO_STRUCT(settings);
154 settings.site_name = p->dest_dsa->site_name;
155 settings.root_dn_str = p->forest->root_dn_str;
156 settings.domain_dn_str = p->domain->dn_str;
157 settings.config_dn_str = p->forest->config_dn_str;
158 settings.schema_dn_str = p->forest->schema_dn_str;
159 settings.netbios_name = p->dest_dsa->netbios_name;
160 settings.realm = s->realm;
161 settings.domain = s->domain_name;
162 settings.server_dn_str = p->dest_dsa->server_dn_str;
163 settings.machine_password = generate_random_password(s, 16, 255);
164 settings.targetdir = s->targetdir;
165 settings.use_ntvfs = true;
166 status = provision_bare(s, s->lp_ctx, &settings, &result);
168 if (!NT_STATUS_IS_OK(status)) {
169 return status;
172 s->ldb = talloc_steal(s, result.samdb);
173 s->lp_ctx = talloc_reparent(talloc_parent(result.lp_ctx), s, result.lp_ctx);
174 s->provision_schema = dsdb_get_schema(s->ldb, s);
175 s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
177 /* wrap the entire vapire operation in a transaction. This
178 isn't just cosmetic - we use this to ensure that linked
179 attribute back links are added at the end by relying on a
180 transaction commit hook in the linked attributes module. We
181 need to do this as the order of objects coming from the
182 server is not sufficiently deterministic to know that the
183 record that a backlink needs to be created in has itself
184 been created before the object containing the forward link
185 has come over the wire */
186 if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
187 return NT_STATUS_FOOBAR;
190 return NT_STATUS_OK;
195 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
196 const struct libnet_BecomeDC_CheckOptions *o)
198 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
200 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
201 s->netbios_name,
202 o->domain->netbios_name, o->domain->dns_name));
204 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
205 o->source_dsa->dns_name, o->source_dsa->site_name));
207 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
208 "\tschema object_version[%u]\n"
209 "\tdomain behavior_version[%u]\n"
210 "\tdomain w2k3_update_revision[%u]\n",
211 o->forest->crossref_behavior_version,
212 o->forest->schema_object_version,
213 o->domain->behavior_version,
214 o->domain->w2k3_update_revision));
216 return NT_STATUS_OK;
219 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
220 const struct libnet_BecomeDC_StoreChunk *c)
222 WERROR status;
223 struct dsdb_schema_prefixmap *pfm_remote;
224 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
225 struct dsdb_schema *provision_schema;
226 uint32_t object_count = 0;
227 struct drsuapi_DsReplicaObjectListItemEx *first_object;
228 uint32_t linked_attributes_count;
229 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
230 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
231 struct dsdb_extended_replicated_objects *schema_objs;
232 struct repsFromTo1 *s_dsa;
233 char *tmp_dns_name;
234 struct ldb_context *schema_ldb;
235 struct ldb_message *msg;
236 struct ldb_message_element *prefixMap_el;
237 uint32_t i;
238 int ret;
239 bool ok;
240 uint64_t seq_num;
241 uint32_t cycle_before_switching;
243 DEBUG(0,("Analyze and apply schema objects\n"));
245 s_dsa = talloc_zero(s, struct repsFromTo1);
246 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
247 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
248 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
250 switch (c->ctr_level) {
251 case 1:
252 mapping_ctr = &c->ctr1->mapping_ctr;
253 object_count = s->schema_part.object_count;
254 first_object = s->schema_part.first_object;
255 linked_attributes_count = 0;
256 linked_attributes = NULL;
257 s_dsa->highwatermark = c->ctr1->new_highwatermark;
258 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
259 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
260 uptodateness_vector = NULL; /* TODO: map it */
261 break;
262 case 6:
263 mapping_ctr = &c->ctr6->mapping_ctr;
264 object_count = s->schema_part.object_count;
265 first_object = s->schema_part.first_object;
266 linked_attributes_count = c->ctr6->linked_attributes_count;
267 linked_attributes = c->ctr6->linked_attributes;
268 s_dsa->highwatermark = c->ctr6->new_highwatermark;
269 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
270 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
271 uptodateness_vector = c->ctr6->uptodateness_vector;
272 break;
273 default:
274 return NT_STATUS_INVALID_PARAMETER;
276 /* We must set these up to ensure the replMetaData is written
277 * correctly, before our NTDS Settings entry is replicated */
278 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
279 if (!ok) {
280 DEBUG(0,("Failed to set cached ntds invocationId\n"));
281 return NT_STATUS_FOOBAR;
283 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
284 if (!ok) {
285 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
286 return NT_STATUS_FOOBAR;
289 status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
290 s, &pfm_remote, NULL);
291 if (!W_ERROR_IS_OK(status)) {
292 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
293 win_errstr(status)));
294 return werror_to_ntstatus(status);
297 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
298 | DRSUAPI_DRS_INIT_SYNC
299 | DRSUAPI_DRS_PER_SYNC;
300 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
302 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
303 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
304 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
305 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
306 s_dsa->other_info->dns_name = tmp_dns_name;
308 if (s->self_made_schema == NULL) {
309 DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
310 return NT_STATUS_INTERNAL_ERROR;
313 schema_ldb = provision_get_schema(s, s->lp_ctx,
314 c->forest->schema_dn_str,
315 &s->prefixmap_blob);
316 if (!schema_ldb) {
317 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
318 "Will continue with local prefixMap\n"));
319 provision_schema = dsdb_get_schema(s->ldb, s);
320 } else {
321 provision_schema = dsdb_get_schema(schema_ldb, s);
322 ret = dsdb_reference_schema(s->ldb, provision_schema, false);
323 if (ret != LDB_SUCCESS) {
324 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
325 return NT_STATUS_UNSUCCESSFUL;
327 talloc_free(schema_ldb);
330 cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
331 "become dc",
332 "schema convert retrial", 1);
334 status = dsdb_repl_resolve_working_schema(s->ldb, s,
335 pfm_remote,
336 cycle_before_switching,
337 provision_schema,
338 s->self_made_schema,
339 object_count,
340 first_object);
341 if (!W_ERROR_IS_OK(status)) {
342 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
343 __location__, win_errstr(status)));
344 return werror_to_ntstatus(status);
347 /* free temp objects for 1st conversion phase */
348 talloc_unlink(s, provision_schema);
351 * attach the schema we just brought over DRS to the ldb,
352 * so we can use it in dsdb_convert_object_ex below
354 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
355 if (ret != LDB_SUCCESS) {
356 DEBUG(0,("Failed to attach working schema from DRS.\n"));
357 return NT_STATUS_FOOBAR;
360 /* we don't want to access the self made schema anymore */
361 s->schema = s->self_made_schema;
362 s->self_made_schema = NULL;
364 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
365 status = dsdb_replicated_objects_convert(s->ldb,
366 s->schema,
367 c->partition->nc.dn,
368 mapping_ctr,
369 object_count,
370 first_object,
371 linked_attributes_count,
372 linked_attributes,
373 s_dsa,
374 uptodateness_vector,
375 c->gensec_skey,
377 s, &schema_objs);
378 if (!W_ERROR_IS_OK(status)) {
379 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
380 return werror_to_ntstatus(status);
383 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
384 for (i=0; i < schema_objs->num_objects; i++) {
385 struct ldb_ldif ldif;
386 fprintf(stdout, "#\n");
387 ldif.changetype = LDB_CHANGETYPE_NONE;
388 ldif.msg = schema_objs->objects[i].msg;
389 ldb_ldif_write_file(s->ldb, stdout, &ldif);
390 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
394 status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
395 if (!W_ERROR_IS_OK(status)) {
396 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
397 return werror_to_ntstatus(status);
400 msg = ldb_msg_new(schema_objs);
401 NT_STATUS_HAVE_NO_MEMORY(msg);
402 msg->dn = schema_objs->partition_dn;
404 /* We must ensure a prefixMap has been written. Unlike other
405 * attributes (including schemaInfo), it is not replicated in
406 * the normal replication stream. We can use the one from
407 * s->prefixmap_blob because we operate with one, unchanging
408 * prefixMap for this entire operation. */
409 ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
410 if (ret != LDB_SUCCESS) {
411 return NT_STATUS_FOOBAR;
413 /* We want to know if a prefixMap was written already, as it
414 * would mean that the above comment was not true, and we have
415 * somehow updated the prefixMap during this transaction */
416 prefixMap_el->flags = LDB_FLAG_MOD_ADD;
418 ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
419 if (ret != LDB_SUCCESS) {
420 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
421 return NT_STATUS_FOOBAR;
424 talloc_free(s_dsa);
425 talloc_free(schema_objs);
427 s->schema = dsdb_get_schema(s->ldb, s);
428 if (!s->schema) {
429 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
430 return NT_STATUS_FOOBAR;
433 return NT_STATUS_OK;
436 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
437 const struct libnet_BecomeDC_StoreChunk *c)
439 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
440 WERROR status;
441 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
442 uint32_t nc_object_count;
443 uint32_t nc_total_received = 0;
444 uint32_t object_count;
445 struct drsuapi_DsReplicaObjectListItemEx *first_object;
446 struct drsuapi_DsReplicaObjectListItemEx *cur;
447 uint32_t nc_linked_attributes_count;
448 uint32_t linked_attributes_count;
450 switch (c->ctr_level) {
451 case 1:
452 mapping_ctr = &c->ctr1->mapping_ctr;
453 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
454 object_count = c->ctr1->object_count;
455 first_object = c->ctr1->first_object;
456 nc_linked_attributes_count = 0;
457 linked_attributes_count = 0;
458 break;
459 case 6:
460 mapping_ctr = &c->ctr6->mapping_ctr;
461 nc_object_count = c->ctr6->nc_object_count;
462 object_count = c->ctr6->object_count;
463 first_object = c->ctr6->first_object;
464 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
465 linked_attributes_count = c->ctr6->linked_attributes_count;
466 break;
467 default:
468 return NT_STATUS_INVALID_PARAMETER;
471 if (!s->schema_part.first_object) {
472 nc_total_received = object_count;
473 } else {
474 nc_total_received = s->schema_part.object_count + object_count;
476 if (nc_object_count) {
477 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
478 c->partition->nc.dn, nc_total_received, nc_object_count,
479 linked_attributes_count, nc_linked_attributes_count));
480 } else {
481 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
482 c->partition->nc.dn, nc_total_received, linked_attributes_count));
485 if (!s->self_made_schema) {
486 WERROR werr;
487 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
488 /* Put the DRS prefixmap aside for the schema we are
489 * about to load in the provision, and into the one we
490 * are making with the help of DRS */
492 mapping_ctr_without_schema_info = *mapping_ctr;
494 /* This strips off the 0xFF schema info from the end,
495 * because we don't want it in the blob */
496 if (mapping_ctr_without_schema_info.num_mappings > 0) {
497 mapping_ctr_without_schema_info.num_mappings--;
499 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
500 if (!W_ERROR_IS_OK(werr)) {
501 return werror_to_ntstatus(werr);
504 /* Set up two manually-constructed schema - the local
505 * schema from the provision will be used to build
506 * one, which will then in turn be used to build the
507 * other. */
508 s->self_made_schema = dsdb_new_schema(s);
509 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
511 s->self_made_schema->base_dn = ldb_dn_new(s->self_made_schema,
512 s->ldb,
513 c->forest->schema_dn_str);
514 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema->base_dn);
516 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
517 if (!W_ERROR_IS_OK(status)) {
518 return werror_to_ntstatus(status);
520 } else {
521 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
522 if (!W_ERROR_IS_OK(status)) {
523 return werror_to_ntstatus(status);
527 if (!s->schema_part.first_object) {
528 s->schema_part.object_count = object_count;
529 s->schema_part.first_object = talloc_steal(s, first_object);
530 } else {
531 s->schema_part.object_count += object_count;
532 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
533 first_object);
535 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
536 s->schema_part.last_object = cur;
538 if (!c->partition->more_data) {
539 return libnet_vampire_cb_apply_schema(s, c);
542 return NT_STATUS_OK;
545 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
546 const struct libnet_BecomeDC_StoreChunk *c)
548 struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
549 WERROR status;
550 struct dsdb_schema *schema;
551 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
552 uint32_t nc_object_count;
553 uint32_t object_count;
554 struct drsuapi_DsReplicaObjectListItemEx *first_object;
555 uint32_t nc_linked_attributes_count;
556 uint32_t linked_attributes_count;
557 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
558 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
559 struct dsdb_extended_replicated_objects *objs;
560 uint32_t req_replica_flags;
561 struct repsFromTo1 *s_dsa;
562 char *tmp_dns_name;
563 uint32_t i;
564 uint64_t seq_num;
565 bool is_exop = false;
567 s_dsa = talloc_zero(s, struct repsFromTo1);
568 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
569 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
570 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
572 switch (c->ctr_level) {
573 case 1:
574 mapping_ctr = &c->ctr1->mapping_ctr;
575 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
576 object_count = c->ctr1->object_count;
577 first_object = c->ctr1->first_object;
578 nc_linked_attributes_count = 0;
579 linked_attributes_count = 0;
580 linked_attributes = NULL;
581 s_dsa->highwatermark = c->ctr1->new_highwatermark;
582 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
583 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
584 uptodateness_vector = NULL; /* TODO: map it */
585 break;
586 case 6:
587 mapping_ctr = &c->ctr6->mapping_ctr;
588 nc_object_count = c->ctr6->nc_object_count;
589 object_count = c->ctr6->object_count;
590 first_object = c->ctr6->first_object;
591 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
592 linked_attributes_count = c->ctr6->linked_attributes_count;
593 linked_attributes = c->ctr6->linked_attributes;
594 s_dsa->highwatermark = c->ctr6->new_highwatermark;
595 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
596 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
597 uptodateness_vector = c->ctr6->uptodateness_vector;
598 break;
599 default:
600 return NT_STATUS_INVALID_PARAMETER;
603 switch (c->req_level) {
604 case 0:
605 /* none */
606 req_replica_flags = 0;
607 break;
608 case 5:
609 if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
610 is_exop = true;
612 req_replica_flags = c->req5->replica_flags;
613 break;
614 case 8:
615 if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
616 is_exop = true;
618 req_replica_flags = c->req8->replica_flags;
619 break;
620 case 10:
621 if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
622 is_exop = true;
624 req_replica_flags = c->req10->replica_flags;
625 break;
626 default:
627 return NT_STATUS_INVALID_PARAMETER;
630 if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
632 * If we only replicate the critical objects
633 * we should not remember what we already
634 * got, as it is incomplete.
636 ZERO_STRUCT(s_dsa->highwatermark);
637 uptodateness_vector = NULL;
640 /* TODO: avoid hardcoded flags */
641 s_dsa->replica_flags = DRSUAPI_DRS_WRIT_REP
642 | DRSUAPI_DRS_INIT_SYNC
643 | DRSUAPI_DRS_PER_SYNC;
644 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
646 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
647 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
648 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
649 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
650 s_dsa->other_info->dns_name = tmp_dns_name;
652 /* we want to show a count per partition */
653 if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
654 s->total_objects = 0;
655 talloc_free(s->last_partition);
656 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
658 s->total_objects += object_count;
660 if (is_exop) {
661 if (nc_object_count) {
662 DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
663 c->partition->nc.dn, s->total_objects, nc_object_count,
664 linked_attributes_count, nc_linked_attributes_count));
665 } else {
666 DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
667 c->partition->nc.dn, s->total_objects, linked_attributes_count));
669 } else {
670 if (nc_object_count) {
671 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
672 c->partition->nc.dn, s->total_objects, nc_object_count,
673 linked_attributes_count, nc_linked_attributes_count));
674 } else {
675 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
676 c->partition->nc.dn, s->total_objects, linked_attributes_count));
681 schema = dsdb_get_schema(s->ldb, NULL);
682 if (!schema) {
683 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
684 return NT_STATUS_INTERNAL_ERROR;
687 status = dsdb_replicated_objects_convert(s->ldb,
688 schema,
689 c->partition->nc.dn,
690 mapping_ctr,
691 object_count,
692 first_object,
693 linked_attributes_count,
694 linked_attributes,
695 s_dsa,
696 uptodateness_vector,
697 c->gensec_skey,
699 s, &objs);
700 if (!W_ERROR_IS_OK(status)) {
701 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
702 return werror_to_ntstatus(status);
705 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
706 for (i=0; i < objs->num_objects; i++) {
707 struct ldb_ldif ldif;
708 fprintf(stdout, "#\n");
709 ldif.changetype = LDB_CHANGETYPE_NONE;
710 ldif.msg = objs->objects[i].msg;
711 ldb_ldif_write_file(s->ldb, stdout, &ldif);
712 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
715 status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
716 if (!W_ERROR_IS_OK(status)) {
717 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
718 return werror_to_ntstatus(status);
721 talloc_free(s_dsa);
722 talloc_free(objs);
724 for (i=0; i < linked_attributes_count; i++) {
725 const struct dsdb_attribute *sa;
727 if (!linked_attributes[i].identifier) {
728 DEBUG(0, ("No linked attribute identifier\n"));
729 return NT_STATUS_FOOBAR;
732 if (!linked_attributes[i].value.blob) {
733 DEBUG(0, ("No linked attribute value\n"));
734 return NT_STATUS_FOOBAR;
737 sa = dsdb_attribute_by_attributeID_id(s->schema,
738 linked_attributes[i].attid);
739 if (!sa) {
740 DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes[i].attid));
741 return NT_STATUS_FOOBAR;
744 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
745 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
746 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
747 dump_data(0,
748 linked_attributes[i].value.blob->data,
749 linked_attributes[i].value.blob->length);
753 return NT_STATUS_OK;
756 static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
757 struct ldb_context *ldb,
758 const char *server_dn_str,
759 const char *netbios_name,
760 const char *realm)
762 int ret;
763 struct ldb_message *msg;
764 struct ldb_message_element *el;
765 struct ldb_dn *server_dn;
766 const char *dNSHostName = strlower_talloc(mem_ctx,
767 talloc_asprintf(mem_ctx,
768 "%s.%s",
769 netbios_name,
770 realm));
771 msg = ldb_msg_new(mem_ctx);
772 if (msg == NULL) {
773 return NT_STATUS_NO_MEMORY;
776 server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
777 if (!server_dn) {
778 return NT_STATUS_INTERNAL_ERROR;
781 msg->dn = server_dn;
782 ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
783 if (ret != LDB_SUCCESS) {
784 return NT_STATUS_INTERNAL_ERROR;
787 ret = ldb_msg_add_steal_string(msg,
788 "dNSHostName",
789 talloc_asprintf(el->values, "%s", dNSHostName));
790 if (ret != LDB_SUCCESS) {
791 return NT_STATUS_INTERNAL_ERROR;
794 ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
795 if (ret != LDB_SUCCESS) {
796 DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
797 ldb_errstring(ldb)));
798 return NT_STATUS_INTERNAL_ERROR;
801 return NT_STATUS_OK;
805 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
806 struct libnet_Vampire *r)
808 struct libnet_JoinDomain *join;
809 struct libnet_Replicate rep;
810 NTSTATUS status;
812 const char *account_name;
813 const char *netbios_name;
815 r->out.error_string = NULL;
817 join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
818 if (!join) {
819 return NT_STATUS_NO_MEMORY;
822 if (r->in.netbios_name != NULL) {
823 netbios_name = r->in.netbios_name;
824 } else {
825 netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
826 if (!netbios_name) {
827 talloc_free(join);
828 r->out.error_string = NULL;
829 return NT_STATUS_NO_MEMORY;
833 account_name = talloc_asprintf(join, "%s$", netbios_name);
834 if (!account_name) {
835 talloc_free(join);
836 r->out.error_string = NULL;
837 return NT_STATUS_NO_MEMORY;
840 /* Re-use the domain we are joining as the domain for the user
841 * to be authenticated with, unless they specified
842 * otherwise */
843 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
845 join->in.domain_name = r->in.domain_name;
846 join->in.account_name = account_name;
847 join->in.netbios_name = netbios_name;
848 join->in.level = LIBNET_JOINDOMAIN_AUTOMATIC;
849 join->in.acct_type = ACB_WSTRUST;
850 join->in.recreate_account = false;
851 status = libnet_JoinDomain(ctx, join, join);
852 if (!NT_STATUS_IS_OK(status)) {
853 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
854 talloc_free(join);
855 return status;
858 rep.in.domain_name = join->out.domain_name;
859 rep.in.netbios_name = netbios_name;
860 rep.in.targetdir = r->in.targetdir;
861 rep.in.domain_sid = join->out.domain_sid;
862 rep.in.realm = join->out.realm;
863 rep.in.server = join->out.samr_binding->host;
864 rep.in.join_password = join->out.join_password;
865 rep.in.kvno = join->out.kvno;
867 status = libnet_Replicate(ctx, mem_ctx, &rep);
869 r->out.domain_sid = join->out.domain_sid;
870 r->out.domain_name = join->out.domain_name;
871 r->out.error_string = rep.out.error_string;
873 return status;
878 NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
879 struct libnet_Replicate *r)
881 struct provision_store_self_join_settings *set_secrets;
882 struct libnet_BecomeDC b;
883 struct libnet_vampire_cb_state *s;
884 struct ldb_message *msg;
885 const char *error_string;
886 int ldb_ret;
887 uint32_t i;
888 NTSTATUS status;
889 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
890 const char *account_name;
891 const char *netbios_name;
893 r->out.error_string = NULL;
895 netbios_name = r->in.netbios_name;
896 account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
897 if (!account_name) {
898 talloc_free(tmp_ctx);
899 r->out.error_string = NULL;
900 return NT_STATUS_NO_MEMORY;
903 /* Re-use the domain we are joining as the domain for the user
904 * to be authenticated with, unless they specified
905 * otherwise */
906 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
908 s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
909 netbios_name, r->in.domain_name, r->in.realm,
910 r->in.targetdir);
911 if (!s) {
912 return NT_STATUS_NO_MEMORY;
914 talloc_steal(s, tmp_ctx);
916 ZERO_STRUCT(b);
918 /* Be more robust:
919 * We now know the domain and realm for sure - if they didn't
920 * put one on the command line, use this for the rest of the
921 * join */
922 cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
923 cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
925 /* Now set these values into the smb.conf - we probably had
926 * empty or useless defaults here from whatever smb.conf we
927 * started with */
928 lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
929 lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
931 b.in.domain_dns_name = r->in.realm;
932 b.in.domain_netbios_name = r->in.domain_name;
933 b.in.domain_sid = r->in.domain_sid;
934 b.in.source_dsa_address = r->in.server;
935 b.in.dest_dsa_netbios_name = netbios_name;
937 b.in.callbacks.private_data = s;
938 b.in.callbacks.check_options = libnet_vampire_cb_check_options;
939 b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db;
940 b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk;
941 b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk;
942 b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk;
944 b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
946 status = libnet_BecomeDC(ctx, s, &b);
947 if (!NT_STATUS_IS_OK(status)) {
948 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
949 talloc_free(s);
950 return status;
953 msg = ldb_msg_new(s);
954 if (!msg) {
955 printf("ldb_msg_new() failed\n");
956 talloc_free(s);
957 return NT_STATUS_NO_MEMORY;
959 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
960 if (!msg->dn) {
961 printf("ldb_msg_new(@ROOTDSE) failed\n");
962 talloc_free(s);
963 return NT_STATUS_NO_MEMORY;
966 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
967 if (ldb_ret != LDB_SUCCESS) {
968 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
969 talloc_free(s);
970 return NT_STATUS_NO_MEMORY;
973 for (i=0; i < msg->num_elements; i++) {
974 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
977 printf("mark ROOTDSE with isSynchronized=TRUE\n");
978 ldb_ret = ldb_modify(s->ldb, msg);
979 if (ldb_ret != LDB_SUCCESS) {
980 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
981 talloc_free(s);
982 return NT_STATUS_INTERNAL_DB_ERROR;
984 /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
985 * the attribute appears on the original DC after replication
987 status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
988 if (!NT_STATUS_IS_OK(status)) {
989 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
990 talloc_free(s);
991 return status;
993 /* prepare the transaction - this prepares to commit all the changes in
994 the ldb from the whole vampire. Note that this
995 triggers the writing of the linked attribute backlinks.
997 if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
998 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
999 return NT_STATUS_INTERNAL_DB_ERROR;
1002 set_secrets = talloc(s, struct provision_store_self_join_settings);
1003 if (!set_secrets) {
1004 r->out.error_string = NULL;
1005 talloc_free(s);
1006 return NT_STATUS_NO_MEMORY;
1009 ZERO_STRUCTP(set_secrets);
1010 set_secrets->domain_name = r->in.domain_name;
1011 set_secrets->realm = r->in.realm;
1012 set_secrets->netbios_name = netbios_name;
1013 set_secrets->secure_channel_type = SEC_CHAN_BDC;
1014 set_secrets->machine_password = r->in.join_password;
1015 set_secrets->key_version_number = r->in.kvno;
1016 set_secrets->domain_sid = r->in.domain_sid;
1018 status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 r->out.error_string = talloc_steal(mem_ctx, error_string);
1021 talloc_free(s);
1022 return status;
1025 /* commit the transaction now we know the secrets were written
1026 * out properly
1028 if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
1029 printf("Failed to commit vampire transaction\n");
1030 return NT_STATUS_INTERNAL_DB_ERROR;
1033 talloc_free(s);
1035 return NT_STATUS_OK;