1/* 2 Unix SMB/CIFS implementation. 3 4 libnet_BecomeDC() tests 5 6 Copyright (C) Stefan Metzmacher <metze@samba.org> 2006 7 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. 12 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. 17 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/>. 20*/ 21 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" 42 43struct 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; 51 52 struct ldb_context *ldb; 53 54 struct { 55 uint32_t object_count; 56 struct drsuapi_DsReplicaObjectListItemEx *first_object; 57 struct drsuapi_DsReplicaObjectListItemEx *last_object; 58 } schema_part; 59 60 const char *targetdir; 61 62 struct loadparm_context *lp_ctx; 63}; 64 65static NTSTATUS test_become_dc_prepare_db(void *private_data, 66 const struct libnet_BecomeDC_PrepareDB *p) 67{ 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; 72 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; 87 88 status = provision_bare(s, s->lp_ctx, &settings, &result); 89 90 s->ldb = result.samdb; 91 s->lp_ctx = result.lp_ctx; 92 return NT_STATUS_OK; 93 94 95} 96 97static NTSTATUS test_become_dc_check_options(void *private_data, 98 const struct libnet_BecomeDC_CheckOptions *o) 99{ 100 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state); 101 102 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n", 103 s->netbios_name, 104 o->domain->netbios_name, o->domain->dns_name)); 105 106 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n", 107 o->source_dsa->dns_name, o->source_dsa->site_name)); 108 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)); 117 118 return NT_STATUS_OK; 119} 120 121static NTSTATUS test_apply_schema(struct test_become_dc_state *s, 122 const struct libnet_BecomeDC_StoreChunk *c) 123{ 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; 144 145 DEBUG(0,("Analyze and apply schema objects\n")); 146 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); 151 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; 177 } 178 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)); 183 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; 189 190 for (cur = first_object; cur; cur = cur->next_object) { 191 bool is_attr = false; 192 bool is_class = false; 193 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; 198 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); 203 } 204 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; 209 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); 213 } 214 215 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) { 216 is_attr = true; 217 } 218 if (val == DRSUAPI_OBJECTCLASS_classSchema) { 219 is_class = true; 220 } 221 } 222 223 break; 224 default: 225 break; 226 } 227 } 228 229 if (is_attr) { 230 struct dsdb_attribute *sa; 231 232 sa = talloc_zero(s->self_made_schema, struct dsdb_attribute); 233 NT_STATUS_HAVE_NO_MEMORY(sa); 234 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); 238 } 239 240 DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *); 241 } 242 243 if (is_class) { 244 struct dsdb_class *sc; 245 246 sc = talloc_zero(s->self_made_schema, struct dsdb_class); 247 NT_STATUS_HAVE_NO_MEMORY(sc); 248 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); 252 } 253 254 DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *); 255 } 256 } 257 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; 262 } 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); 266 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); 281 } 282 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); 291 } 292 } 293 294 msg = ldb_msg_new(objs); 295 NT_STATUS_HAVE_NO_MEMORY(msg); 296 msg->dn = objs->partition_dn; 297 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); 302 } 303 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; 308 } 309 prefixMap_el->flags = LDB_FLAG_MOD_REPLACE; 310 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; 315 } 316 317 talloc_free(s_dsa); 318 talloc_free(objs); 319 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; 323 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; 333 } 334 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; 339 } 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; 344 } 345 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; 350 } 351 352 return NT_STATUS_OK; 353} 354 355static NTSTATUS test_become_dc_schema_chunk(void *private_data, 356 const struct libnet_BecomeDC_StoreChunk *c) 357{ 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; 367 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; 387 } 388 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)); 396 } 397 398 if (!s->schema) { 399 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx)); 400 401 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema); 402 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); 406 } 407 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); 413 } 414 } 415 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); 423 } 424 for (cur = first_object; cur->next_object; cur = cur->next_object) {} 425 s->schema_part.last_object = cur; 426 427 if (!c->partition->more_data) { 428 return test_apply_schema(s, c); 429 } 430 431 return NT_STATUS_OK; 432} 433 434static NTSTATUS test_become_dc_store_chunk(void *private_data, 435 const struct libnet_BecomeDC_StoreChunk *c) 436{ 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; 452 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); 457 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; 487 } 488 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)); 493 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; 499 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)); 507 } 508 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); 523 } 524 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); 533 } 534 } 535 talloc_free(s_dsa); 536 talloc_free(objs); 537 538 for (i=0; i < linked_attributes_count; i++) { 539 const struct dsdb_attribute *sa; 540 541 if (!linked_attributes[i].identifier) { 542 return NT_STATUS_FOOBAR; 543 } 544 545 if (!linked_attributes[i].value.blob) { 546 return NT_STATUS_FOOBAR; 547 } 548 549 sa = dsdb_attribute_by_attributeID_id(s->schema, 550 linked_attributes[i].attid); 551 if (!sa) { 552 return NT_STATUS_FOOBAR; 553 } 554 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); 561 } 562 } 563 564 return NT_STATUS_OK; 565} 566 567bool torture_net_become_dc(struct torture_context *torture) 568{ 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; 578 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" ); 582 583 s = talloc_zero(torture, struct test_become_dc_state); 584 if (!s) return false; 585 586 s->tctx = torture; 587 s->lp_ctx = torture->lp_ctx; 588 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"; 592 } 593 594 s->targetdir = location; 595 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; 604 } 605 606 s->ctx = libnet_context_init(torture->ev, torture->lp_ctx); 607 s->ctx->cred = cmdline_credentials; 608 609 s->ldb = ldb_init(s, torture->ev); 610 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; 617 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; 624 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; 630 } 631 632 msg = ldb_msg_new(s); 633 if (!msg) { 634 printf("ldb_msg_new() failed\n"); 635 ret = false; 636 goto cleanup; 637 } 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; 643 } 644 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; 650 } 651 652 for (i=0; i < msg->num_elements; i++) { 653 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; 654 } 655 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; 662 } 663 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; 667 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; 678 } 679 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; 685 } 686 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; 691 } 692 693cleanup: 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; 699 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; 704 } 705 706 /* Leave domain. */ 707 torture_leave_domain(torture, s->tj); 708 709 talloc_free(s); 710 return ret; 711} 712