static void next_open(struct benchopen_state *state) { state->count++; state->pending_file_num = state->next_file_num; state->next_file_num = (state->next_file_num+1) % (3*nprocs); DEBUG(2,("[%d] opening %u\n", state->client_num, state->pending_file_num)); state->open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX; state->open_parms.ntcreatex.in.flags = 0; state->open_parms.ntcreatex.in.root_fid.fnum = 0; state->open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; state->open_parms.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; state->open_parms.ntcreatex.in.alloc_size = 0; state->open_parms.ntcreatex.in.share_access = 0; state->open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF; state->open_parms.ntcreatex.in.create_options = 0; state->open_parms.ntcreatex.in.impersonation = 0; state->open_parms.ntcreatex.in.security_flags = 0; state->open_parms.ntcreatex.in.fname = fnames[state->pending_file_num]; state->req_open = smb_raw_open_send(state->tree, &state->open_parms); state->req_open->async.fn = open_completed; state->req_open->async.private_data = state; }
bool torture_samba3_oplock_logoff(struct torture_context *tctx, struct smbcli_state *cli) { union smb_open io; const char *fname = "testfile"; bool ret = false; struct smbcli_request *req; struct smb_echo echo_req; smbcli_unlink(cli->tree, fname); ZERO_STRUCT(io); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.access_mask = SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.fname = "testfile"; torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io), NT_STATUS_OK, ret, done, "first smb_open on the file failed"); /* * Create a conflicting open, causing the one-second delay */ torture_assert_goto(tctx, req = smb_raw_open_send(cli->tree, &io), ret, done, "smb_raw_open_send on the file failed"); /* * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3 * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors * as long as the client is still connected. */ torture_assert_ntstatus_equal_goto(tctx, smb_raw_ulogoff(cli->session), NT_STATUS_OK, ret, done, "ulogoff failed failed"); echo_req.in.repeat_count = 1; echo_req.in.size = 1; echo_req.in.data = discard_const_p(uint8_t, ""); torture_assert_ntstatus_equal_goto(tctx, smb_raw_echo(cli->session->transport, &echo_req), NT_STATUS_OK, ret, done, "smb_raw_echo failed"); ret = true; done: return ret; }
/* test disconnect after async open */ static bool test_disconnect_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { union smb_open io; struct smbcli_request *req1, *req2; NTSTATUS status; printf("trying open/disconnect\n"); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.flags = 0; io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = BASEDIR "\\open.dat"; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); io.ntcreatex.in.share_access = 0; req1 = smb_raw_open_send(cli->tree, &io); req2 = smb_raw_open_send(cli->tree, &io); if (!req1 || !req2) { printf("test_disconnect_open: smb_raw_open_send() " "returned NULL\n"); return false; } status = smbcli_chkpath(cli->tree, "\\"); CHECK_STATUS(status, NT_STATUS_OK); talloc_free(cli); return true; }
/* open a file */ static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_open *io) { struct cvfs_private *p = ntvfs->private_data; struct smbcli_request *c_req; struct ntvfs_handle *h; struct cvfs_file *f; NTSTATUS status; SETUP_PID; if (io->generic.level != RAW_OPEN_GENERIC && p->map_generic) { return ntvfs_map_open(ntvfs, req, io); } status = ntvfs_handle_new(ntvfs, req, &h); NT_STATUS_NOT_OK_RETURN(status); f = talloc_zero(h, struct cvfs_file); NT_STATUS_HAVE_NO_MEMORY(f); f->h = h; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { union smb_handle *file; status = smb_raw_open(p->tree, req, io); NT_STATUS_NOT_OK_RETURN(status); SMB_OPEN_OUT_FILE(io, file); f->fnum = file->fnum; file->ntvfs = NULL; status = ntvfs_handle_set_backend_data(f->h, p->ntvfs, f); NT_STATUS_NOT_OK_RETURN(status); file->ntvfs = f->h; DLIST_ADD(p->files, f); return NT_STATUS_OK; } c_req = smb_raw_open_send(p->tree, io); ASYNC_RECV_TAIL_F(io, async_open, f); }
/* test the delayed reply to a open that leads to a sharing violation */ static bool test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { union smb_open io; NTSTATUS status; int fnum1, fnum2; bool ret = true; struct smbcli_request *req1, *req2; struct timeval tv; double d; printf("Testing multiplexed open/open/close\n"); printf("send first open\n"); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.flags = 0; io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = BASEDIR "\\open.dat"; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum1 = io.ntcreatex.out.file.fnum; printf("send 2nd open, non-conflicting\n"); io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum2 = io.ntcreatex.out.file.fnum; tv = timeval_current(); printf("send 3rd open, conflicting\n"); io.ntcreatex.in.share_access = 0; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); d = timeval_elapsed(&tv); if (d < 0.5 || d > 1.5) { printf("bad timeout for conflict - %.2f should be 1.0\n", d); } else { printf("open delay %.2f\n", d); } printf("send async open, conflicting\n"); tv = timeval_current(); req1 = smb_raw_open_send(cli->tree, &io); printf("send 2nd async open, conflicting\n"); tv = timeval_current(); req2 = smb_raw_open_send(cli->tree, &io); printf("close first sync open\n"); smbcli_close(cli->tree, fnum1); printf("cancel 2nd async open (should be ignored)\n"); smb_raw_ntcancel(req2); d = timeval_elapsed(&tv); if (d > 0.25) { printf("bad timeout after cancel - %.2f should be <0.25\n", d); ret = false; } printf("close the 2nd sync open\n"); smbcli_close(cli->tree, fnum2); printf("see if the 1st async open now succeeded\n"); status = smb_raw_open_recv(req1, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); d = timeval_elapsed(&tv); if (d > 0.25) { printf("bad timeout for async conflict - %.2f should be <0.25\n", d); ret = false; } else { printf("async open delay %.2f\n", d); } printf("2nd async open should have timed out\n"); status = smb_raw_open_recv(req2, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); d = timeval_elapsed(&tv); if (d < 0.8) { printf("bad timeout for async conflict - %.2f should be 1.0\n", d); } printf("close the 1st async open\n"); smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); done: return ret; }
/**************************************************************************** Open a file - sync interface ****************************************************************************/ _PUBLIC_ NTSTATUS smb_raw_open(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, union smb_open *parms) { struct smbcli_request *req = smb_raw_open_send(tree, parms); return smb_raw_open_recv(req, mem_ctx, parms); }
bool torture_samba3_oplock_logoff(struct torture_context *tctx) { struct smbcli_state *cli; NTSTATUS status; uint16_t fnum1; union smb_open io; const char *fname = "testfile"; bool ret = false; struct smbcli_request *req; struct smb_echo echo_req; if (!torture_open_connection(&cli, tctx, 0)) { ret = false; goto done; } smbcli_unlink(cli->tree, fname); ZERO_STRUCT(io); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.access_mask = SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.fname = "testfile"; status = smb_raw_open(cli->tree, tctx, &io); if (!NT_STATUS_IS_OK(status)) { d_printf("first smb_open failed: %s\n", nt_errstr(status)); ret = false; goto done; } fnum1 = io.ntcreatex.out.file.fnum; /* * Create a conflicting open, causing the one-second delay */ req = smb_raw_open_send(cli->tree, &io); if (req == NULL) { d_printf("smb_raw_open_send failed\n"); ret = false; goto done; } /* * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3 * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors * as long as the client is still connected. */ status = smb_raw_ulogoff(cli->session); if (!NT_STATUS_IS_OK(status)) { d_printf("ulogoff failed: %s\n", nt_errstr(status)); ret = false; goto done; } echo_req.in.repeat_count = 1; echo_req.in.size = 1; echo_req.in.data = discard_const_p(uint8_t, ""); status = smb_raw_echo(cli->session->transport, &echo_req); if (!NT_STATUS_IS_OK(status)) { d_printf("smb_raw_echo returned %s\n", nt_errstr(status)); ret = false; goto done; } ret = true; done: return ret; }
/* called when a open completes */ static void open_completed(struct smbcli_request *req) { struct benchopen_state *state = (struct benchopen_state *)req->async.private_data; TALLOC_CTX *tmp_ctx = talloc_new(state->mem_ctx); NTSTATUS status; status = smb_raw_open_recv(req, tmp_ctx, &state->open_parms); talloc_free(tmp_ctx); state->req_open = NULL; if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) || NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT) || NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) { talloc_free(state->tree); talloc_free(state->cli); state->tree = NULL; state->cli = NULL; num_connected--; DEBUG(0,("[%u] reopening connection to %s\n", state->client_num, state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), reopen_connection, state); return; } if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { DEBUG(2,("[%d] retrying open %d\n", state->client_num, state->pending_file_num)); state->open_retries++; state->req_open = smb_raw_open_send(state->tree, &state->open_parms); state->req_open->async.fn = open_completed; state->req_open->async.private_data = state; return; } if (!NT_STATUS_IS_OK(status)) { open_failed++; DEBUG(0,("[%u] open failed %d - %s\n", state->client_num, state->pending_file_num, nt_errstr(status))); return; } state->close_file_num = state->open_file_num; state->close_fnum = state->open_fnum; state->open_file_num = state->pending_file_num; state->open_fnum = state->open_parms.ntcreatex.out.file.fnum; DEBUG(2,("[%d] open completed %d (fnum[%d])\n", state->client_num, state->open_file_num, state->open_fnum)); if (state->close_fnum != -1) { next_close(state); } next_open(state); }
static bool test_session_reauth2(struct torture_context *tctx, struct smbcli_state *cli) { char *random_string; char *fname; union smb_open io_open; struct smb_composite_sesssetup io_sesssetup; union smb_fileinfo io_qsecdesc; struct smbcli_request *req; struct cli_credentials *anon_creds; NTSTATUS status; uint16_t fnum; ssize_t nwritten; uint16_t vuid1 = cli->session->vuid; random_string = generate_random_str(tctx, 8); torture_assert(tctx, (random_string != NULL), "memory allocation failed"); fname = talloc_asprintf(tctx, "raw_session_reauth2_%s.dat", random_string); talloc_free(random_string); torture_assert(tctx, (fname != NULL), "memory allocation failed"); smbcli_unlink(cli->tree, fname); smbcli_oplock_handler(cli->transport, test_session_reauth2_oplock_timeout, cli->tree); /* base ntcreatex parms */ ZERO_STRUCT(io_open); io_open.generic.level = RAW_OPEN_NTCREATEX; io_open.ntcreatex.in.root_fid.fnum = 0; io_open.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE; io_open.ntcreatex.in.alloc_size = 0; io_open.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io_open.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; io_open.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io_open.ntcreatex.in.create_options = 0; io_open.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io_open.ntcreatex.in.security_flags = 0; io_open.ntcreatex.in.fname = fname; torture_comment(tctx, "open with batch oplock\n"); io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; status = smb_raw_open(cli->tree, tctx, &io_open); torture_assert_ntstatus_ok(tctx, status, "smb_raw_open failed"); fnum = io_open.ntcreatex.out.file.fnum; torture_assert( tctx, (io_open.ntcreatex.out.oplock_level == BATCH_OPLOCK_RETURN), "did not get batch oplock"); io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; req = smb_raw_open_send(cli->tree, &io_open); torture_assert(tctx, (req != NULL), "memory allocation failed"); /* * Make sure the open went through */ status = smbcli_chkpath(cli->tree, "\\"); torture_assert_ntstatus_ok(tctx, status, "smb_chkpath failed"); status = smbcli_nt_delete_on_close(cli->tree, fnum, true); torture_assert_ntstatus_ok(tctx, status, "could not set delete on " "close"); anon_creds = cli_credentials_init_anon(tctx); torture_assert(tctx, (anon_creds != NULL), "memory allocation failed"); ZERO_STRUCT(io_sesssetup); io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey; io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities; io_sesssetup.in.credentials = anon_creds; io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx); io_sesssetup.in.gensec_settings = lpcfg_gensec_settings( tctx, tctx->lp_ctx); status = smb_composite_sesssetup(cli->session, &io_sesssetup); torture_assert_ntstatus_ok(tctx, status, "setup2 failed"); torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2"); status = smbcli_close(cli->tree, fnum); torture_assert_ntstatus_ok(tctx, status, "close failed"); status = smb_raw_open_recv(req, tctx, &io_open); torture_assert_ntstatus_ok(tctx, status, "2nd open failed"); fnum = io_open.ntcreatex.out.file.fnum; nwritten = smbcli_write(cli->tree, fnum, 0, fname, 0, strlen(fname)); torture_assert(tctx, (nwritten == strlen(fname)), "smbcli_write failed"); ZERO_STRUCT(io_qsecdesc); io_qsecdesc.query_secdesc.level = RAW_FILEINFO_SEC_DESC; io_qsecdesc.query_secdesc.in.file.fnum = fnum; io_qsecdesc.query_secdesc.in.secinfo_flags = SECINFO_OWNER; status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc); torture_assert_ntstatus_equal( tctx, status, NT_STATUS_ACCESS_DENIED, "anon qsecdesc did not return ACCESS_DENIED"); ZERO_STRUCT(io_sesssetup); io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey; io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities; io_sesssetup.in.credentials = cmdline_credentials; io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx); io_sesssetup.in.gensec_settings = lpcfg_gensec_settings( tctx, tctx->lp_ctx); status = smb_composite_sesssetup(cli->session, &io_sesssetup); torture_assert_ntstatus_ok(tctx, status, "setup3 failed"); torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2"); status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc); torture_assert_ntstatus_ok(tctx, status, "2nd qsecdesc failed"); status = smbcli_nt_delete_on_close(cli->tree, fnum, true); torture_assert_ntstatus_ok(tctx, status, "could not set delete on " "close"); status = smbcli_close(cli->tree, fnum); torture_assert_ntstatus_ok(tctx, status, "close failed"); return true; }