static void async_open_recv(struct smbcli_request *req) { struct async_context *c = req->async.private_data; NTSTATUS status; DEBUG(1, ("IN: async_open_recv\n")); status = smb_raw_open_recv(req, c, c->io_open); c->rreq = NULL; if (NT_STATUS_IS_OK(status)) #ifdef USE_OPENX_CALL c->fd = c->io_open->openx.out.file.fnum; #else c->fd = c->io_open->ntcreatex.out.file.fnum; #endif talloc_free(c->io_open); c->io_open = 0; if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("ERROR: smb_raw_open_recv - %s\n", nt_errstr(status))); if (c->cb_error) c->cb_error(c->cb_ctx, ASYNC_OPEN_RECV, status); return; } if (c->cb_open) c->cb_open(c->cb_ctx); async_read(c); }
static NTSTATUS smb_raw_openX_name_blob(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, union smb_open *parms, const DATA_BLOB *pname_blob) { struct smbcli_request *req = smb_raw_openX_name_blob_send(tree, parms, pname_blob); return smb_raw_open_recv(req, mem_ctx, parms); }
/* a handler for async open replies */ static void async_open(struct smbcli_request *c_req) { struct async_info *async = c_req->async.private_data; struct cvfs_private *cvfs = async->cvfs; struct ntvfs_request *req = async->req; struct cvfs_file *f = async->f; union smb_open *io = async->parms; union smb_handle *file; talloc_free(async); req->async_states->status = smb_raw_open_recv(c_req, req, io); SMB_OPEN_OUT_FILE(io, file); f->fnum = file->fnum; file->ntvfs = NULL; if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed; req->async_states->status = ntvfs_handle_set_backend_data(f->h, cvfs->ntvfs, f); if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed; file->ntvfs = f->h; DLIST_ADD(cvfs->files, f); failed: req->async_states->send_fn(req); }
/* 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); }
/* 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; }