s4-repl: don't do double replication
[Samba/aatanasov.git] / source4 / torture / libnet / libnet_BecomeDC.c
blob81bdf342b210d959a648481e835b8d9d9b819269
1 /*
2 Unix SMB/CIFS implementation.
4 libnet_BecomeDC() tests
6 Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "lib/cmdline/popt_common.h"
24 #include "torture/torture.h"
25 #include "torture/rpc/rpc.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 "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"
37 #include "lib/ldb_wrap.h"
38 #include "auth/auth.h"
39 #include "param/param.h"
40 #include "torture/util.h"
41 #include "param/provision.h"
43 struct test_become_dc_state {
44 struct libnet_context *ctx;
45 struct torture_context *tctx;
46 const char *netbios_name;
47 struct test_join *tj;
48 struct cli_credentials *machine_account;
49 struct dsdb_schema *self_made_schema;
50 const struct dsdb_schema *schema;
52 struct ldb_context *ldb;
54 struct {
55 uint32_t object_count;
56 struct drsuapi_DsReplicaObjectListItemEx *first_object;
57 struct drsuapi_DsReplicaObjectListItemEx *last_object;
58 } schema_part;
60 const char *targetdir;
62 struct loadparm_context *lp_ctx;
65 static NTSTATUS test_become_dc_prepare_db(void *private_data,
66 const struct libnet_BecomeDC_PrepareDB *p)
68 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
69 struct provision_settings settings;
70 struct provision_result result;
71 NTSTATUS status;
73 settings.site_name = p->dest_dsa->site_name;
74 settings.root_dn_str = p->forest->root_dn_str;
75 settings.domain_dn_str = p->domain->dn_str;
76 settings.config_dn_str = p->forest->config_dn_str;
77 settings.schema_dn_str = p->forest->schema_dn_str;
78 settings.server_dn_str = torture_join_server_dn_str(s->tj);
79 settings.invocation_id = &p->dest_dsa->invocation_id;
80 settings.netbios_name = p->dest_dsa->netbios_name;
81 settings.host_ip = NULL;
82 settings.realm = torture_join_dom_dns_name(s->tj);
83 settings.domain = torture_join_dom_netbios_name(s->tj);
84 settings.ntds_dn_str = p->dest_dsa->ntds_dn_str;
85 settings.machine_password = cli_credentials_get_password(s->machine_account);
86 settings.targetdir = s->targetdir;
88 status = provision_bare(s, s->lp_ctx, &settings, &result);
90 s->ldb = result.samdb;
91 s->lp_ctx = result.lp_ctx;
92 return NT_STATUS_OK;
97 static NTSTATUS test_become_dc_check_options(void *private_data,
98 const struct libnet_BecomeDC_CheckOptions *o)
100 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
102 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
103 s->netbios_name,
104 o->domain->netbios_name, o->domain->dns_name));
106 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
107 o->source_dsa->dns_name, o->source_dsa->site_name));
109 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
110 "\tschema object_version[%u]\n"
111 "\tdomain behavior_version[%u]\n"
112 "\tdomain w2k3_update_revision[%u]\n",
113 o->forest->crossref_behavior_version,
114 o->forest->schema_object_version,
115 o->domain->behavior_version,
116 o->domain->w2k3_update_revision));
118 return NT_STATUS_OK;
121 static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
122 const struct libnet_BecomeDC_StoreChunk *c)
124 WERROR status;
125 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
126 uint32_t object_count;
127 struct drsuapi_DsReplicaObjectListItemEx *first_object;
128 struct drsuapi_DsReplicaObjectListItemEx *cur;
129 uint32_t linked_attributes_count;
130 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
131 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
132 struct dsdb_extended_replicated_objects *objs;
133 struct repsFromTo1 *s_dsa;
134 char *tmp_dns_name;
135 struct ldb_message *msg;
136 struct ldb_val prefixMap_val;
137 struct ldb_message_element *prefixMap_el;
138 struct ldb_val schemaInfo_val;
139 char *sam_ldb_path;
140 uint32_t i;
141 int ret;
142 bool ok;
143 uint64_t seq_num;
145 DEBUG(0,("Analyze and apply schema objects\n"));
147 s_dsa = talloc_zero(s, struct repsFromTo1);
148 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
149 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
150 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
152 switch (c->ctr_level) {
153 case 1:
154 mapping_ctr = &c->ctr1->mapping_ctr;
155 object_count = s->schema_part.object_count;
156 first_object = s->schema_part.first_object;
157 linked_attributes_count = 0;
158 linked_attributes = NULL;
159 s_dsa->highwatermark = c->ctr1->new_highwatermark;
160 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
161 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
162 uptodateness_vector = NULL; /* TODO: map it */
163 break;
164 case 6:
165 mapping_ctr = &c->ctr6->mapping_ctr;
166 object_count = s->schema_part.object_count;
167 first_object = s->schema_part.first_object;
168 linked_attributes_count = 0; /* TODO: ! */
169 linked_attributes = NULL; /* TODO: ! */;
170 s_dsa->highwatermark = c->ctr6->new_highwatermark;
171 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
172 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
173 uptodateness_vector = c->ctr6->uptodateness_vector;
174 break;
175 default:
176 return NT_STATUS_INVALID_PARAMETER;
179 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
180 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
181 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
182 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
184 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
185 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
186 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
187 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
188 s_dsa->other_info->dns_name = tmp_dns_name;
190 for (cur = first_object; cur; cur = cur->next_object) {
191 bool is_attr = false;
192 bool is_class = false;
194 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
195 struct drsuapi_DsReplicaAttribute *a;
196 uint32_t j;
197 const char *oid = NULL;
199 a = &cur->object.attribute_ctr.attributes[i];
200 status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
201 if (!W_ERROR_IS_OK(status)) {
202 return werror_to_ntstatus(status);
205 switch (a->attid) {
206 case DRSUAPI_ATTRIBUTE_objectClass:
207 for (j=0; j < a->value_ctr.num_values; j++) {
208 uint32_t val = 0xFFFFFFFF;
210 if (a->value_ctr.values[i].blob
211 && a->value_ctr.values[i].blob->length == 4) {
212 val = IVAL(a->value_ctr.values[i].blob->data,0);
215 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
216 is_attr = true;
218 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
219 is_class = true;
223 break;
224 default:
225 break;
229 if (is_attr) {
230 struct dsdb_attribute *sa;
232 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
233 NT_STATUS_HAVE_NO_MEMORY(sa);
235 status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
236 if (!W_ERROR_IS_OK(status)) {
237 return werror_to_ntstatus(status);
240 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
243 if (is_class) {
244 struct dsdb_class *sc;
246 sc = talloc_zero(s->self_made_schema, struct dsdb_class);
247 NT_STATUS_HAVE_NO_MEMORY(sc);
249 status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
250 if (!W_ERROR_IS_OK(status)) {
251 return werror_to_ntstatus(status);
254 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
258 /* attach the schema to the ldb */
259 ret = dsdb_set_schema(s->ldb, s->self_made_schema);
260 if (ret != LDB_SUCCESS) {
261 return NT_STATUS_FOOBAR;
263 /* we don't want to access the self made schema anymore */
264 s->self_made_schema = NULL;
265 s->schema = dsdb_get_schema(s->ldb);
267 status = dsdb_extended_replicated_objects_commit(s->ldb,
268 c->partition->nc.dn,
269 mapping_ctr,
270 object_count,
271 first_object,
272 linked_attributes_count,
273 linked_attributes,
274 s_dsa,
275 uptodateness_vector,
276 c->gensec_skey,
277 s, &objs, &seq_num);
278 if (!W_ERROR_IS_OK(status)) {
279 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
280 return werror_to_ntstatus(status);
283 if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
284 for (i=0; i < objs->num_objects; i++) {
285 struct ldb_ldif ldif;
286 fprintf(stdout, "#\n");
287 ldif.changetype = LDB_CHANGETYPE_NONE;
288 ldif.msg = objs->objects[i].msg;
289 ldb_ldif_write_file(s->ldb, stdout, &ldif);
290 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
294 msg = ldb_msg_new(objs);
295 NT_STATUS_HAVE_NO_MEMORY(msg);
296 msg->dn = objs->partition_dn;
298 status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
299 if (!W_ERROR_IS_OK(status)) {
300 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
301 return werror_to_ntstatus(status);
304 /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
305 ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
306 if (ret != LDB_SUCCESS) {
307 return NT_STATUS_FOOBAR;
309 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
311 ret = ldb_modify(s->ldb, msg);
312 if (ret != LDB_SUCCESS) {
313 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
314 return NT_STATUS_FOOBAR;
317 talloc_free(s_dsa);
318 talloc_free(objs);
320 /* reopen the ldb */
321 talloc_free(s->ldb); /* this also free's the s->schema, because dsdb_set_schema() steals it */
322 s->schema = NULL;
324 sam_ldb_path = talloc_asprintf(s, "%s/%s", s->targetdir, "private/sam.ldb");
325 DEBUG(0,("Reopen the SAM LDB with system credentials and a already stored schema: %s\n", sam_ldb_path));
326 s->ldb = ldb_wrap_connect(s, s->tctx->ev, s->tctx->lp_ctx, sam_ldb_path,
327 system_session(s, s->tctx->lp_ctx),
328 NULL, 0, NULL);
329 if (!s->ldb) {
330 DEBUG(0,("Failed to open '%s'\n",
331 sam_ldb_path));
332 return NT_STATUS_INTERNAL_DB_ERROR;
335 ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
336 if (!ok) {
337 DEBUG(0,("Failed to set cached ntds invocationId\n"));
338 return NT_STATUS_FOOBAR;
340 ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
341 if (!ok) {
342 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
343 return NT_STATUS_FOOBAR;
346 s->schema = dsdb_get_schema(s->ldb);
347 if (!s->schema) {
348 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
349 return NT_STATUS_FOOBAR;
352 return NT_STATUS_OK;
355 static NTSTATUS test_become_dc_schema_chunk(void *private_data,
356 const struct libnet_BecomeDC_StoreChunk *c)
358 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
359 WERROR status;
360 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
361 uint32_t nc_object_count;
362 uint32_t object_count;
363 struct drsuapi_DsReplicaObjectListItemEx *first_object;
364 struct drsuapi_DsReplicaObjectListItemEx *cur;
365 uint32_t nc_linked_attributes_count;
366 uint32_t linked_attributes_count;
368 switch (c->ctr_level) {
369 case 1:
370 mapping_ctr = &c->ctr1->mapping_ctr;
371 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
372 object_count = c->ctr1->object_count;
373 first_object = c->ctr1->first_object;
374 nc_linked_attributes_count = 0;
375 linked_attributes_count = 0;
376 break;
377 case 6:
378 mapping_ctr = &c->ctr6->mapping_ctr;
379 nc_object_count = c->ctr6->nc_object_count;
380 object_count = c->ctr6->object_count;
381 first_object = c->ctr6->first_object;
382 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
383 linked_attributes_count = c->ctr6->linked_attributes_count;
384 break;
385 default:
386 return NT_STATUS_INVALID_PARAMETER;
389 if (nc_object_count) {
390 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
391 c->partition->nc.dn, object_count, nc_object_count,
392 linked_attributes_count, nc_linked_attributes_count));
393 } else {
394 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u\n",
395 c->partition->nc.dn, object_count, linked_attributes_count));
398 if (!s->schema) {
399 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
401 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
403 status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
404 if (!W_ERROR_IS_OK(status)) {
405 return werror_to_ntstatus(status);
408 s->schema = s->self_made_schema;
409 } else {
410 status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
411 if (!W_ERROR_IS_OK(status)) {
412 return werror_to_ntstatus(status);
416 if (!s->schema_part.first_object) {
417 s->schema_part.object_count = object_count;
418 s->schema_part.first_object = talloc_steal(s, first_object);
419 } else {
420 s->schema_part.object_count += object_count;
421 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
422 first_object);
424 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
425 s->schema_part.last_object = cur;
427 if (!c->partition->more_data) {
428 return test_apply_schema(s, c);
431 return NT_STATUS_OK;
434 static NTSTATUS test_become_dc_store_chunk(void *private_data,
435 const struct libnet_BecomeDC_StoreChunk *c)
437 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
438 WERROR status;
439 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
440 uint32_t nc_object_count;
441 uint32_t object_count;
442 struct drsuapi_DsReplicaObjectListItemEx *first_object;
443 uint32_t nc_linked_attributes_count;
444 uint32_t linked_attributes_count;
445 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
446 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
447 struct dsdb_extended_replicated_objects *objs;
448 struct repsFromTo1 *s_dsa;
449 char *tmp_dns_name;
450 uint32_t i;
451 uint64_t seq_num;
453 s_dsa = talloc_zero(s, struct repsFromTo1);
454 NT_STATUS_HAVE_NO_MEMORY(s_dsa);
455 s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
456 NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
458 switch (c->ctr_level) {
459 case 1:
460 mapping_ctr = &c->ctr1->mapping_ctr;
461 nc_object_count = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
462 object_count = c->ctr1->object_count;
463 first_object = c->ctr1->first_object;
464 nc_linked_attributes_count = 0;
465 linked_attributes_count = 0;
466 linked_attributes = NULL;
467 s_dsa->highwatermark = c->ctr1->new_highwatermark;
468 s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
469 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
470 uptodateness_vector = NULL; /* TODO: map it */
471 break;
472 case 6:
473 mapping_ctr = &c->ctr6->mapping_ctr;
474 nc_object_count = c->ctr6->nc_object_count;
475 object_count = c->ctr6->object_count;
476 first_object = c->ctr6->first_object;
477 nc_linked_attributes_count = c->ctr6->nc_linked_attributes_count;
478 linked_attributes_count = c->ctr6->linked_attributes_count;
479 linked_attributes = c->ctr6->linked_attributes;
480 s_dsa->highwatermark = c->ctr6->new_highwatermark;
481 s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
482 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
483 uptodateness_vector = c->ctr6->uptodateness_vector;
484 break;
485 default:
486 return NT_STATUS_INVALID_PARAMETER;
489 s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
490 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
491 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
492 memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
494 tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
495 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
496 tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
497 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
498 s_dsa->other_info->dns_name = tmp_dns_name;
500 if (nc_object_count) {
501 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
502 c->partition->nc.dn, object_count, nc_object_count,
503 linked_attributes_count, nc_linked_attributes_count));
504 } else {
505 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u\n",
506 c->partition->nc.dn, object_count, linked_attributes_count));
509 status = dsdb_extended_replicated_objects_commit(s->ldb,
510 c->partition->nc.dn,
511 mapping_ctr,
512 object_count,
513 first_object,
514 linked_attributes_count,
515 linked_attributes,
516 s_dsa,
517 uptodateness_vector,
518 c->gensec_skey,
519 s, &objs, &seq_num);
520 if (!W_ERROR_IS_OK(status)) {
521 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
522 return werror_to_ntstatus(status);
525 if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
526 for (i=0; i < objs->num_objects; i++) {
527 struct ldb_ldif ldif;
528 fprintf(stdout, "#\n");
529 ldif.changetype = LDB_CHANGETYPE_NONE;
530 ldif.msg = objs->objects[i].msg;
531 ldb_ldif_write_file(s->ldb, stdout, &ldif);
532 NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
535 talloc_free(s_dsa);
536 talloc_free(objs);
538 for (i=0; i < linked_attributes_count; i++) {
539 const struct dsdb_attribute *sa;
541 if (!linked_attributes[i].identifier) {
542 return NT_STATUS_FOOBAR;
545 if (!linked_attributes[i].value.blob) {
546 return NT_STATUS_FOOBAR;
549 sa = dsdb_attribute_by_attributeID_id(s->schema,
550 linked_attributes[i].attid);
551 if (!sa) {
552 return NT_STATUS_FOOBAR;
555 if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
556 DEBUG(0,("# %s\n", sa->lDAPDisplayName));
557 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
558 dump_data(0,
559 linked_attributes[i].value.blob->data,
560 linked_attributes[i].value.blob->length);
564 return NT_STATUS_OK;
567 bool torture_net_become_dc(struct torture_context *torture)
569 bool ret = true;
570 NTSTATUS status;
571 struct libnet_BecomeDC b;
572 struct libnet_UnbecomeDC u;
573 struct test_become_dc_state *s;
574 struct ldb_message *msg;
575 int ldb_ret;
576 uint32_t i;
577 char *sam_ldb_path;
579 char *location = NULL;
580 torture_assert_ntstatus_ok(torture, torture_temp_dir(torture, "libnet_BecomeDC", &location),
581 "torture_temp_dir should return NT_STATUS_OK" );
583 s = talloc_zero(torture, struct test_become_dc_state);
584 if (!s) return false;
586 s->tctx = torture;
587 s->lp_ctx = torture->lp_ctx;
589 s->netbios_name = lp_parm_string(torture->lp_ctx, NULL, "become dc", "smbtorture dc");
590 if (!s->netbios_name || !s->netbios_name[0]) {
591 s->netbios_name = "smbtorturedc";
594 s->targetdir = location;
596 /* Join domain as a member server. */
597 s->tj = torture_join_domain(torture, s->netbios_name,
598 ACB_WSTRUST,
599 &s->machine_account);
600 if (!s->tj) {
601 DEBUG(0, ("%s failed to join domain as workstation\n",
602 s->netbios_name));
603 return false;
606 s->ctx = libnet_context_init(torture->ev, torture->lp_ctx);
607 s->ctx->cred = cmdline_credentials;
609 s->ldb = ldb_init(s, torture->ev);
611 ZERO_STRUCT(b);
612 b.in.domain_dns_name = torture_join_dom_dns_name(s->tj);
613 b.in.domain_netbios_name = torture_join_dom_netbios_name(s->tj);
614 b.in.domain_sid = torture_join_sid(s->tj);
615 b.in.source_dsa_address = torture_setting_string(torture, "host", NULL);
616 b.in.dest_dsa_netbios_name = s->netbios_name;
618 b.in.callbacks.private_data = s;
619 b.in.callbacks.check_options = test_become_dc_check_options;
620 b.in.callbacks.prepare_db = test_become_dc_prepare_db;
621 b.in.callbacks.schema_chunk = test_become_dc_schema_chunk;
622 b.in.callbacks.config_chunk = test_become_dc_store_chunk;
623 b.in.callbacks.domain_chunk = test_become_dc_store_chunk;
625 status = libnet_BecomeDC(s->ctx, s, &b);
626 if (!NT_STATUS_IS_OK(status)) {
627 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
628 ret = false;
629 goto cleanup;
632 msg = ldb_msg_new(s);
633 if (!msg) {
634 printf("ldb_msg_new() failed\n");
635 ret = false;
636 goto cleanup;
638 msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
639 if (!msg->dn) {
640 printf("ldb_msg_new(@ROOTDSE) failed\n");
641 ret = false;
642 goto cleanup;
645 ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
646 if (ldb_ret != LDB_SUCCESS) {
647 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
648 ret = false;
649 goto cleanup;
652 for (i=0; i < msg->num_elements; i++) {
653 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
656 printf("mark ROOTDSE with isSynchronized=TRUE\n");
657 ldb_ret = ldb_modify(s->ldb, msg);
658 if (ldb_ret != LDB_SUCCESS) {
659 printf("ldb_modify() failed: %d\n", ldb_ret);
660 ret = false;
661 goto cleanup;
664 /* reopen the ldb */
665 talloc_free(s->ldb); /* this also free's the s->schema, because dsdb_set_schema() steals it */
666 s->schema = NULL;
668 sam_ldb_path = talloc_asprintf(s, "%s/%s", s->targetdir, "private/sam.ldb");
669 DEBUG(0,("Reopen the SAM LDB with system credentials and all replicated data: %s\n", sam_ldb_path));
670 s->ldb = ldb_wrap_connect(s, s->tctx->ev, s->lp_ctx, sam_ldb_path,
671 system_session(s, s->lp_ctx),
672 NULL, 0, NULL);
673 if (!s->ldb) {
674 DEBUG(0,("Failed to open '%s'\n",
675 sam_ldb_path));
676 ret = false;
677 goto cleanup;
680 s->schema = dsdb_get_schema(s->ldb);
681 if (!s->schema) {
682 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
683 ret = false;
684 goto cleanup;
687 /* Make sure we get this from the command line */
688 if (lp_parm_bool(torture->lp_ctx, NULL, "become dc", "do not unjoin", false)) {
689 talloc_free(s);
690 return ret;
693 cleanup:
694 ZERO_STRUCT(u);
695 u.in.domain_dns_name = torture_join_dom_dns_name(s->tj);
696 u.in.domain_netbios_name = torture_join_dom_netbios_name(s->tj);
697 u.in.source_dsa_address = torture_setting_string(torture, "host", NULL);
698 u.in.dest_dsa_netbios_name = s->netbios_name;
700 status = libnet_UnbecomeDC(s->ctx, s, &u);
701 if (!NT_STATUS_IS_OK(status)) {
702 printf("libnet_UnbecomeDC() failed - %s\n", nt_errstr(status));
703 ret = false;
706 /* Leave domain. */
707 torture_leave_domain(torture, s->tj);
709 talloc_free(s);
710 return ret;