/* test UDP/138 ntlogon requests */ static bool nbt_test_ntlogon(struct torture_context *tctx) { struct dgram_mailslot_handler *dgmslot; struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); struct socket_address *dest; struct test_join *join_ctx; const struct dom_sid *dom_sid; struct cli_credentials *machine_credentials; const char *myaddress; struct nbt_netlogon_packet logon; struct nbt_netlogon_response *response; struct nbt_name myname; NTSTATUS status; struct timeval tv = timeval_current(); struct socket_address *socket_address; const char *address; struct nbt_name name; struct interface *ifaces; name.name = lp_workgroup(tctx->lp_ctx); name.type = NBT_NAME_LOGON; name.scope = NULL; /* do an initial name resolution to find its IP */ torture_assert_ntstatus_ok(tctx, resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev), talloc_asprintf(tctx, "Failed to resolve %s", name.name)); load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces); myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address)); socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, myaddress, lp_dgram_port(tctx->lp_ctx)); torture_assert(tctx, socket_address != NULL, "Error getting address"); /* try receiving replies on port 138 first, which will only work if we are root and smbd/nmbd are not running - fall back to listening on any port, which means replies from most windows versions won't be seen */ status = socket_listen(dgmsock->sock, socket_address, 0, 0); if (!NT_STATUS_IS_OK(status)) { talloc_free(socket_address); socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, myaddress, 0); torture_assert(tctx, socket_address != NULL, "Error getting address"); socket_listen(dgmsock->sock, socket_address, 0, 0); } join_ctx = torture_join_domain(tctx, TEST_NAME, ACB_WSTRUST, &machine_credentials); dom_sid = torture_join_sid(join_ctx); torture_assert(tctx, join_ctx != NULL, talloc_asprintf(tctx, "Failed to join domain %s as %s\n", lp_workgroup(tctx->lp_ctx), TEST_NAME)); /* setup a temporary mailslot listener for replies */ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC, netlogon_handler, NULL); ZERO_STRUCT(logon); logon.command = LOGON_SAM_LOGON_REQUEST; logon.req.logon.request_count = 0; logon.req.logon.computer_name = TEST_NAME; logon.req.logon.user_name = TEST_NAME"$"; logon.req.logon.mailslot_name = dgmslot->mailslot_name; logon.req.logon.acct_control = ACB_WSTRUST; /* Try with a SID this time */ logon.req.logon.sid = *dom_sid; logon.req.logon.nt_version = 1; logon.req.logon.lmnt_token = 0xFFFF; logon.req.logon.lm20_token = 0xFFFF; make_nbt_name_client(&myname, TEST_NAME); dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, address, lp_dgram_port(tctx->lp_ctx)); torture_assert(tctx, dest != NULL, "Error getting address"); status = dgram_mailslot_netlogon_send(dgmsock, &name, dest, NBT_MAILSLOT_NTLOGON, &myname, &logon); torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request"); while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) { event_loop_once(dgmsock->event_ctx); } response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response); torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet"); torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response"); map_netlogon_samlogon_response(&response->data.samlogon); torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command"); torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response"); /* setup a temporary mailslot listener for replies */ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC, netlogon_handler, NULL); ZERO_STRUCT(logon); logon.command = LOGON_SAM_LOGON_REQUEST; logon.req.logon.request_count = 0; logon.req.logon.computer_name = TEST_NAME; logon.req.logon.user_name = TEST_NAME"$"; logon.req.logon.mailslot_name = dgmslot->mailslot_name; logon.req.logon.acct_control = ACB_WSTRUST; /* Leave sid as all zero */ logon.req.logon.nt_version = 1; logon.req.logon.lmnt_token = 0xFFFF; logon.req.logon.lm20_token = 0xFFFF; make_nbt_name_client(&myname, TEST_NAME); dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, address, lp_dgram_port(tctx->lp_ctx)); torture_assert(tctx, dest != NULL, "Error getting address"); status = dgram_mailslot_netlogon_send(dgmsock, &name, dest, NBT_MAILSLOT_NTLOGON, &myname, &logon); torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request"); while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) { event_loop_once(dgmsock->event_ctx); } response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response); torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet"); torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response"); map_netlogon_samlogon_response(&response->data.samlogon); torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command"); torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response"); /* setup (another) temporary mailslot listener for replies */ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC, netlogon_handler, NULL); ZERO_STRUCT(logon); logon.command = LOGON_PRIMARY_QUERY; logon.req.pdc.computer_name = TEST_NAME; logon.req.pdc.mailslot_name = dgmslot->mailslot_name; logon.req.pdc.unicode_name = TEST_NAME; logon.req.pdc.nt_version = 1; logon.req.pdc.lmnt_token = 0xFFFF; logon.req.pdc.lm20_token = 0xFFFF; make_nbt_name_client(&myname, TEST_NAME); dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, address, lp_dgram_port(tctx->lp_ctx)); torture_assert(tctx, dest != NULL, "Error getting address"); status = dgram_mailslot_netlogon_send(dgmsock, &name, dest, NBT_MAILSLOT_NTLOGON, &myname, &logon); torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request"); while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) { event_loop_once(dgmsock->event_ctx); } response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response); torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet"); torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response"); torture_assert_int_equal(tctx, response->data.get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command"); torture_leave_domain(tctx, join_ctx); /* setup (another) temporary mailslot listener for replies */ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC, netlogon_handler, NULL); ZERO_STRUCT(logon); logon.command = LOGON_PRIMARY_QUERY; logon.req.pdc.computer_name = TEST_NAME; logon.req.pdc.mailslot_name = dgmslot->mailslot_name; logon.req.pdc.unicode_name = TEST_NAME; logon.req.pdc.nt_version = 1; logon.req.pdc.lmnt_token = 0xFFFF; logon.req.pdc.lm20_token = 0xFFFF; make_nbt_name_client(&myname, TEST_NAME); dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, address, lp_dgram_port(tctx->lp_ctx)); torture_assert(tctx, dest != NULL, "Error getting address"); status = dgram_mailslot_netlogon_send(dgmsock, &name, dest, NBT_MAILSLOT_NTLOGON, &myname, &logon); torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request"); while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) { event_loop_once(dgmsock->event_ctx); } response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response); torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet"); torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response"); torture_assert_int_equal(tctx, response->data.get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command"); return true; }
bool test_DsCrackNames(struct torture_context *tctx, struct DsPrivate *priv) { NTSTATUS status; const char *err_msg; struct drsuapi_DsCrackNames r; union drsuapi_DsNameRequest req; uint32_t level_out; union drsuapi_DsNameCtr ctr; struct drsuapi_DsNameString names[1]; const char *dns_domain; const char *nt4_domain; const char *FQDN_1779_name; struct ldb_context *ldb; struct ldb_dn *FQDN_1779_dn; struct ldb_dn *realm_dn; const char *realm_dn_str; const char *realm_canonical; const char *realm_canonical_ex; const char *user_principal_name; char *user_principal_name_short; const char *service_principal_name; const char *canonical_name; const char *canonical_ex_name; const char *dom_sid; const char *test_dc = torture_join_netbios_name(priv->join); struct dcerpc_pipe *p = priv->drs_pipe; TALLOC_CTX *mem_ctx = priv; ZERO_STRUCT(r); r.in.bind_handle = &priv->bind_handle; r.in.level = 1; r.in.req = &req; r.in.req->req1.codepage = 1252; /* german */ r.in.req->req1.language = 0x00000407; /* german */ r.in.req->req1.count = 1; r.in.req->req1.names = names; r.in.req->req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS; r.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY; r.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; r.out.level_out = &level_out; r.out.ctr = &ctr; dom_sid = dom_sid_string(mem_ctx, torture_join_sid(priv->join)); names[0].str = dom_sid; torture_comment(tctx, "Testing DsCrackNames with name '%s' desired format:%d\n", names[0].str, r.in.req->req1.format_desired); status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr); torture_fail(tctx, err_msg); } else if (!W_ERROR_IS_OK(r.out.result)) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result)); torture_fail(tctx, err_msg); } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d", r.out.ctr->ctr1->array[0].status); torture_fail(tctx, err_msg); } dns_domain = r.out.ctr->ctr1->array[0].dns_domain_name; nt4_domain = r.out.ctr->ctr1->array[0].result_name; r.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_GUID; torture_comment(tctx, "Testing DsCrackNames with name '%s' desired format:%d\n", names[0].str, r.in.req->req1.format_desired); status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr); torture_fail(tctx, err_msg); } else if (!W_ERROR_IS_OK(r.out.result)) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result)); torture_fail(tctx, err_msg); } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d", r.out.ctr->ctr1->array[0].status); torture_fail(tctx, err_msg); } priv->domain_dns_name = r.out.ctr->ctr1->array[0].dns_domain_name; priv->domain_guid_str = r.out.ctr->ctr1->array[0].result_name; GUID_from_string(priv->domain_guid_str, &priv->domain_guid); r.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; torture_comment(tctx, "Testing DsCrackNames with name '%s' desired format:%d\n", names[0].str, r.in.req->req1.format_desired); status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr); torture_fail(tctx, err_msg); } else if (!W_ERROR_IS_OK(r.out.result)) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result)); torture_fail(tctx, err_msg); } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d", r.out.ctr->ctr1->array[0].status); torture_fail(tctx, err_msg); } ldb = ldb_init(mem_ctx, tctx->ev); realm_dn_str = r.out.ctr->ctr1->array[0].result_name; realm_dn = ldb_dn_new(mem_ctx, ldb, realm_dn_str); realm_canonical = ldb_dn_canonical_string(mem_ctx, realm_dn); if (strcmp(realm_canonical, talloc_asprintf(mem_ctx, "%s/", dns_domain))!= 0) { err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical name failed: %s != %s!", realm_canonical, talloc_asprintf(mem_ctx, "%s/", dns_domain)); torture_fail(tctx, err_msg); }; realm_canonical_ex = ldb_dn_canonical_ex_string(mem_ctx, realm_dn); if (strcmp(realm_canonical_ex, talloc_asprintf(mem_ctx, "%s\n", dns_domain))!= 0) { err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical ex name failed: %s != %s!", realm_canonical, talloc_asprintf(mem_ctx, "%s\n", dns_domain)); torture_fail(tctx, err_msg); }; r.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; r.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; names[0].str = nt4_domain; torture_comment(tctx, "Testing DsCrackNames with name '%s' desired format:%d\n", names[0].str, r.in.req->req1.format_desired); status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr); torture_fail(tctx, err_msg); } else if (!W_ERROR_IS_OK(r.out.result)) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result)); torture_fail(tctx, err_msg); } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d", r.out.ctr->ctr1->array[0].status); torture_fail(tctx, err_msg); } priv->domain_obj_dn = r.out.ctr->ctr1->array[0].result_name; r.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; r.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc); torture_comment(tctx, "Testing DsCrackNames with name '%s' desired format:%d\n", names[0].str, r.in.req->req1.format_desired); status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr); torture_fail(tctx, err_msg); } else if (!W_ERROR_IS_OK(r.out.result)) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result)); torture_fail(tctx, err_msg); } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d", r.out.ctr->ctr1->array[0].status); torture_fail(tctx, err_msg); } FQDN_1779_name = r.out.ctr->ctr1->array[0].result_name; r.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID; r.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; names[0].str = priv->domain_guid_str; torture_comment(tctx, "Testing DsCrackNames with name '%s' desired format:%d\n", names[0].str, r.in.req->req1.format_desired); status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr); torture_fail(tctx, err_msg); } else if (!W_ERROR_IS_OK(r.out.result)) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result)); torture_fail(tctx, err_msg); } else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d", r.out.ctr->ctr1->array[0].status); torture_fail(tctx, err_msg); } if (strcmp(priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name) != 0) { err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed to return same DNS name - expected %s got %s", priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name); torture_fail(tctx, err_msg); } FQDN_1779_dn = ldb_dn_new(mem_ctx, ldb, FQDN_1779_name); canonical_name = ldb_dn_canonical_string(mem_ctx, FQDN_1779_dn); canonical_ex_name = ldb_dn_canonical_ex_string(mem_ctx, FQDN_1779_dn); user_principal_name = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, dns_domain); /* form up a user@DOMAIN */ user_principal_name_short = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, nt4_domain); /* variable nt4_domain includs a trailing \ */ user_principal_name_short[strlen(user_principal_name_short) - 1] = '\0'; service_principal_name = talloc_asprintf(mem_ctx, "HOST/%s", test_dc); { struct { enum drsuapi_DsNameFormat format_offered; enum drsuapi_DsNameFormat format_desired; const char *comment; const char *str; const char *expected_str; const char *expected_dns; enum drsuapi_DsNameStatus status; enum drsuapi_DsNameStatus alternate_status; enum drsuapi_DsNameFlags flags; bool skip; } crack[] = { { .format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779, .str = user_principal_name, .expected_str = FQDN_1779_name, .status = DRSUAPI_DS_NAME_STATUS_OK }, { .format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, .format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779, .str = user_principal_name_short, .expected_str = FQDN_1779_name, .status = DRSUAPI_DS_NAME_STATUS_OK }, { .format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
bool torture_net_become_dc(struct torture_context *torture) { bool ret = true; NTSTATUS status; struct libnet_BecomeDC b; struct libnet_UnbecomeDC u; struct libnet_vampire_cb_state *s; struct ldb_message *msg; int ldb_ret; uint32_t i; char *private_dir; const char *address; struct nbt_name name; const char *netbios_name; struct cli_credentials *machine_account; struct test_join *tj; struct loadparm_context *lp_ctx; struct ldb_context *ldb; struct libnet_context *ctx; struct dsdb_schema *schema; char *location = NULL; torture_assert_ntstatus_ok(torture, torture_temp_dir(torture, "libnet_BecomeDC", &location), "torture_temp_dir should return NT_STATUS_OK" ); netbios_name = lpcfg_parm_string(torture->lp_ctx, NULL, "become dc", "smbtorture dc"); if (!netbios_name || !netbios_name[0]) { netbios_name = "smbtorturedc"; } make_nbt_name_server(&name, torture_setting_string(torture, "host", NULL)); /* do an initial name resolution to find its IP */ status = resolve_name_ex(lpcfg_resolve_context(torture->lp_ctx), 0, 0, &name, torture, &address, torture->ev); torture_assert_ntstatus_ok(torture, status, talloc_asprintf(torture, "Failed to resolve %s - %s\n", name.name, nt_errstr(status))); /* Join domain as a member server. */ tj = torture_join_domain(torture, netbios_name, ACB_WSTRUST, &machine_account); torture_assert(torture, tj, talloc_asprintf(torture, "%s failed to join domain as workstation\n", netbios_name)); s = libnet_vampire_cb_state_init(torture, torture->lp_ctx, torture->ev, netbios_name, torture_join_dom_netbios_name(tj), torture_join_dom_dns_name(tj), location); torture_assert(torture, s, "libnet_vampire_cb_state_init"); ctx = libnet_context_init(torture->ev, torture->lp_ctx); ctx->cred = cmdline_credentials; ZERO_STRUCT(b); b.in.domain_dns_name = torture_join_dom_dns_name(tj); b.in.domain_netbios_name = torture_join_dom_netbios_name(tj); b.in.domain_sid = torture_join_sid(tj); b.in.source_dsa_address = address; b.in.dest_dsa_netbios_name = netbios_name; b.in.callbacks.private_data = s; b.in.callbacks.check_options = libnet_vampire_cb_check_options; b.in.callbacks.prepare_db = libnet_vampire_cb_prepare_db; b.in.callbacks.schema_chunk = libnet_vampire_cb_schema_chunk; b.in.callbacks.config_chunk = libnet_vampire_cb_store_chunk; b.in.callbacks.domain_chunk = libnet_vampire_cb_store_chunk; status = libnet_BecomeDC(ctx, s, &b); torture_assert_ntstatus_ok_goto(torture, status, ret, cleanup, talloc_asprintf(torture, "libnet_BecomeDC() failed - %s %s\n", nt_errstr(status), b.out.error_string)); ldb = libnet_vampire_cb_ldb(s); msg = ldb_msg_new(s); torture_assert_int_equal_goto(torture, (msg?1:0), 1, ret, cleanup, "ldb_msg_new() failed\n"); msg->dn = ldb_dn_new(msg, ldb, "@ROOTDSE"); torture_assert_int_equal_goto(torture, (msg->dn?1:0), 1, ret, cleanup, "ldb_msg_new(@ROOTDSE) failed\n"); ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE"); torture_assert_int_equal_goto(torture, ldb_ret, LDB_SUCCESS, ret, cleanup, "ldb_msg_add_string(msg, isSynchronized, TRUE) failed\n"); for (i=0; i < msg->num_elements; i++) { msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; } torture_comment(torture, "mark ROOTDSE with isSynchronized=TRUE\n"); ldb_ret = ldb_modify(libnet_vampire_cb_ldb(s), msg); torture_assert_int_equal_goto(torture, ldb_ret, LDB_SUCCESS, ret, cleanup, "ldb_modify() failed\n"); /* commit the transaction now we know the secrets were written * out properly */ ldb_ret = ldb_transaction_commit(ldb); torture_assert_int_equal_goto(torture, ldb_ret, LDB_SUCCESS, ret, cleanup, "ldb_transaction_commit() failed\n"); /* reopen the ldb */ talloc_unlink(s, ldb); lp_ctx = libnet_vampire_cb_lp_ctx(s); private_dir = talloc_asprintf(s, "%s/%s", location, "private"); lpcfg_set_cmdline(lp_ctx, "private dir", private_dir); torture_comment(torture, "Reopen the SAM LDB with system credentials and all replicated data: %s\n", private_dir); ldb = samdb_connect(s, torture->ev, lp_ctx, system_session(lp_ctx), 0); torture_assert_goto(torture, ldb != NULL, ret, cleanup, talloc_asprintf(torture, "Failed to open '%s/sam.ldb'\n", private_dir)); torture_assert_goto(torture, dsdb_uses_global_schema(ldb), ret, cleanup, "Uses global schema"); schema = dsdb_get_schema(ldb, s); torture_assert_goto(torture, schema != NULL, ret, cleanup, "Failed to get loaded dsdb_schema\n"); /* Make sure we get this from the command line */ if (lpcfg_parm_bool(torture->lp_ctx, NULL, "become dc", "do not unjoin", false)) { talloc_free(s); return ret; } cleanup: ZERO_STRUCT(u); u.in.domain_dns_name = torture_join_dom_dns_name(tj); u.in.domain_netbios_name = torture_join_dom_netbios_name(tj); u.in.source_dsa_address = address; u.in.dest_dsa_netbios_name = netbios_name; status = libnet_UnbecomeDC(ctx, s, &u); torture_assert_ntstatus_ok(torture, status, talloc_asprintf(torture, "libnet_UnbecomeDC() failed - %s %s\n", nt_errstr(status), u.out.error_string)); /* Leave domain. */ torture_leave_domain(torture, tj); talloc_free(s); return ret; }