/* tries the unusual lockingX locktype bits */ static bool torture_locktest6(struct torture_context *tctx, struct smbcli_state *cli) { const char *fname[1] = { "\\lock6.txt" }; int i; int fnum; NTSTATUS status; if (!torture_setup_dir(cli, BASEDIR)) { return false; } for (i=0;i<1;i++) { torture_comment(tctx, "Testing %s\n", fname[i]); smbcli_unlink(cli->tree, fname[i]); fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE); status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE); smbcli_close(cli->tree, fnum); torture_comment(tctx, "CHANGE_LOCKTYPE gave %s\n", nt_errstr(status)); fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE); status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK); smbcli_close(cli->tree, fnum); torture_comment(tctx, "CANCEL_LOCK gave %s\n", nt_errstr(status)); smbcli_unlink(cli->tree, fname[i]); } return true; }
bool torture_samba3_rootdirfid(struct torture_context *tctx, struct smbcli_state *cli) { uint16_t dnum; union smb_open io; const char *fname = "testfile"; bool ret = false; 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_DIRECTORY; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_READ; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.fname = "\\"; torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io), NT_STATUS_OK, ret, done, "smb_open on the directory failed: %s\n"); dnum = io.ntcreatex.out.file.fnum; io.ntcreatex.in.flags = NTCREATEX_FLAGS_REQUEST_OPLOCK | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; io.ntcreatex.in.root_fid.fnum = dnum; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; 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.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.fname = fname; torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io), NT_STATUS_OK, ret, done, "smb_open on the file failed"); smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); smbcli_close(cli->tree, dnum); smbcli_unlink(cli->tree, fname); ret = true; done: return ret; }
/* This test checks that 1) the server does not allow an unlink on a file that is open */ BOOL torture_unlinktest(struct torture_context *tctx, struct smbcli_state *cli) { const char *fname = BASEDIR "\\unlink.tst"; int fnum; BOOL correct = True; union smb_open io; NTSTATUS status; torture_assert(tctx, torture_setup_dir(cli, BASEDIR), talloc_asprintf(tctx, "Failed setting up %s", BASEDIR)); cli->session->pid = 1; torture_comment(tctx, "Opening a file\n"); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "open of %s failed (%s)", fname, smbcli_errstr(cli->tree))); torture_comment(tctx, "Unlinking a open file\n"); torture_assert(tctx, !NT_STATUS_IS_OK(smbcli_unlink(cli->tree, fname)), "server allowed unlink on an open file"); correct = check_error(__location__, cli, ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, fname); torture_comment(tctx, "testing unlink after ntcreatex with DELETE access\n"); io.ntcreatex.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid = 0; io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; io.ntcreatex.in.file_attr = 0; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; status = smb_raw_open(cli->tree, cli, &io); torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "failed to open %s", fname)); torture_assert(tctx, !NT_STATUS_IS_OK(smbcli_unlink(cli->tree, fname)), "server allowed unlink on an open file"); correct = check_error(__location__, cli, ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return correct; }
/* recursively descend a tree deleting all files returns the number of files deleted, or -1 on error */ int smbcli_deltree(struct smbcli_tree *tree, const char *dname) { char *mask; struct delete_state dstate; NTSTATUS status; dstate.tree = tree; dstate.total_deleted = 0; dstate.failed = false; /* it might be a file */ status = smbcli_unlink(tree, dname); if (NT_STATUS_IS_OK(smbcli_unlink(tree, dname))) { return 1; } if (NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_OBJECT_NAME_NOT_FOUND) || NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_OBJECT_PATH_NOT_FOUND) || NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_NO_SUCH_FILE) || NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_DOS(ERRDOS, ERRbadfile))) { return 0; } if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) { /* it could be read-only */ status = smbcli_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL, 0); if (NT_STATUS_IS_OK(smbcli_unlink(tree, dname))) { return 1; } } asprintf(&mask, "%s\\*", dname); smbcli_unlink(dstate.tree, mask); smbcli_list(dstate.tree, mask, FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, delete_fn, &dstate); free(mask); status = smbcli_rmdir(dstate.tree, dname); if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) { /* it could be read-only */ status = smbcli_setatr(dstate.tree, dname, FILE_ATTRIBUTE_NORMAL, 0); status = smbcli_rmdir(dstate.tree, dname); } if (NT_STATUS_IS_ERR(status)) { DEBUG(2,("Failed to delete %s - %s\n", dname, smbcli_errstr(dstate.tree))); return -1; } dstate.total_deleted++; if (dstate.failed) { return -1; } return dstate.total_deleted; }
/* basic testing of all RAW_FILEINFO_* calls for each call we test that it succeeds, and where possible test for consistency between the calls. */ BOOL torture_raw_qfileinfo(struct torture_context *torture) { struct smbcli_state *cli; BOOL ret = True; TALLOC_CTX *mem_ctx; int fnum; const char *fname = "\\torture_qfileinfo.txt"; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_qfileinfo"); fnum = create_complex_file(cli, mem_ctx, fname); if (fnum == -1) { printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); ret = False; goto done; } ret = torture_raw_qfileinfo_internals(torture, mem_ctx, cli->tree, fnum, fname, False /* is_ipc */); smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, fname); done: torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
NTSTATUS svc_UploadService(const char *hostname, struct cli_credentials * credentials, int force) { struct smb_composite_savefile *io; struct smbcli_state *cli; NTSTATUS status; status = smbcli_full_connection(NULL, &cli, hostname, "ADMIN$", NULL, credentials, NULL); NT_ERR(status, 1, "Failed to open ADMIN$ share"); if (!force) { int fd = smbcli_open(cli->tree, "winexesvc.exe", O_RDONLY, DENY_NONE); if (fd >= 0) { smbcli_close(cli->tree, fd); return status; } } else { smbcli_unlink(cli->tree, "winexesvc.exe"); } io = talloc_zero(cli->tree, struct smb_composite_savefile); io->in.fname = "winexesvc.exe"; io->in.data = winexesvc_exe; io->in.size = winexesvc_exe_len; status = smb_composite_savefile(cli->tree, io); NT_ERR(status, 1, "Failed to save ADMIN$/%s", io->in.fname); talloc_free(io); smbcli_tdis(cli); return status; }
static int ejs_unlink(MprVarHandle eid, int argc, MprVar **argv) { struct smbcli_tree *tree; NTSTATUS result; if (argc != 2) { ejsSetErrorMsg(eid, "unlink(): invalid number of args"); return -1; } if (!IS_TREE_HANDLE(argv[0])) { ejsSetErrorMsg(eid, "first arg is not a tree handle"); return -1; } tree = argv[0]->ptr; if (!mprVarIsString(argv[1]->type)) { ejsSetErrorMsg(eid, "arg 2 must be a string"); return -1; } result = smbcli_unlink(tree, argv[1]->string); mpr_Return(eid, mprNTSTATUS(result)); return 0; }
static void test_mask(int argc, char *argv[], TALLOC_CTX *mem_ctx, struct smbcli_state *cli) { char *mask, *file; int l1, l2, i, l; int mc_len = strlen(maskchars); int fc_len = strlen(filechars); smbcli_mkdir(cli->tree, "\\masktest"); smbcli_unlink(cli->tree, "\\masktest\\*"); if (argc >= 2) { while (argc >= 2) { mask = talloc_strdup(mem_ctx, "\\masktest\\"); file = talloc_strdup(mem_ctx, "\\masktest\\"); mask = talloc_strdup_append(mask, argv[0]); file = talloc_strdup_append(file, argv[1]); testpair(mem_ctx, cli, mask, file); argv += 2; argc -= 2; } goto finished; } while (1) { l1 = 1 + random() % max_length; l2 = 1 + random() % max_length; mask = talloc_strdup(mem_ctx, "\\masktest\\"); file = talloc_strdup(mem_ctx, "\\masktest\\"); mask = talloc_realloc_size(mem_ctx, mask, strlen(mask)+l1+1); file = talloc_realloc_size(mem_ctx, file, strlen(file)+l2+1); l = strlen(mask); for (i=0;i<l1;i++) { mask[i+l] = maskchars[random() % mc_len]; } mask[l+l1] = 0; for (i=0;i<l2;i++) { file[i+l] = filechars[random() % fc_len]; } file[l+l2] = 0; if (ISDOT(file+l) || ISDOTDOT(file+l) || ISDOTDOT(mask+l)) { continue; } if (strspn(file+l, ".") == strlen(file+l)) continue; testpair(mem_ctx, cli, mask, file); if (NumLoops && (--NumLoops == 0)) break; } finished: smbcli_rmdir(cli->tree, "\\masktest"); talloc_free(mem_ctx); }
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; }
/* open a file N times on the server and just hold them open used for testing performance when there are N file handles alopenn */ bool torture_holdopen(struct torture_context *tctx, struct smbcli_state *cli) { int i, fnum; const char *fname = "\\holdopen.dat"; NTSTATUS status; smbcli_unlink(cli->tree, fname); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum == -1) { torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); return false; } smbcli_close(cli->tree, fnum); for (i=0;i<torture_numops;i++) { union smb_open op; op.generic.level = RAW_OPEN_NTCREATEX; op.ntcreatex.in.root_fid.fnum = 0; op.ntcreatex.in.flags = 0; op.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA; op.ntcreatex.in.create_options = 0; op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; op.ntcreatex.in.alloc_size = 0; op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; op.ntcreatex.in.security_flags = 0; op.ntcreatex.in.fname = fname; status = smb_raw_open(cli->tree, tctx, &op); if (!NT_STATUS_IS_OK(status)) { torture_warning(tctx, "open %d failed\n", i); continue; } if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "opened %d file\r", i); fflush(stdout); } } torture_comment(tctx, "\nStarting pings\n"); while (1) { struct smb_echo ec; status = smb_raw_echo(cli->transport, &ec); torture_comment(tctx, "."); fflush(stdout); sleep(15); } return true; }
/* callback function for torture_deltree() */ static void delete_fn(struct clilist_file_info *finfo, const char *name, void *state) { struct delete_state *dstate = (struct delete_state *)state; char *s, *n; if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) { return; } n = strdup(name); n[strlen(n)-1] = 0; asprintf(&s, "%s%s", n, finfo->name); if (finfo->attrib & FILE_ATTRIBUTE_READONLY) { if (NT_STATUS_IS_ERR(smbcli_setatr(dstate->tree, s, 0, 0))) { DEBUG(2,("Failed to remove READONLY on %s - %s\n", s, smbcli_errstr(dstate->tree))); } } if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) { char *s2; asprintf(&s2, "%s\\*", s); smbcli_unlink(dstate->tree, s2); smbcli_list(dstate->tree, s2, FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, delete_fn, state); free(s2); if (NT_STATUS_IS_ERR(smbcli_rmdir(dstate->tree, s))) { DEBUG(2,("Failed to delete %s - %s\n", s, smbcli_errstr(dstate->tree))); dstate->failed = true; } dstate->total_deleted++; } else { if (NT_STATUS_IS_ERR(smbcli_unlink(dstate->tree, s))) { DEBUG(2,("Failed to delete %s - %s\n", s, smbcli_errstr(dstate->tree))); dstate->failed = true; } dstate->total_deleted++; } free(s); free(n); }
NTSTATUS svc_uninstall(const char *hostname, struct cli_credentials * credentials) { NTSTATUS status; struct dcerpc_pipe *svc_pipe; struct policy_handle scm_handle; struct policy_handle svc_handle; struct SERVICE_STATUS svc_status; status = svc_pipe_connect(&svc_pipe, hostname, credentials); NT_ERR(status, 1, "Cannot connect to svcctl pipe"); status = svc_OpenSCManager(svc_pipe, hostname, &scm_handle); NT_ERR(status, 1, "OpenSCManager failed"); status = svc_OpenService(svc_pipe, &scm_handle, "winexesvc", &svc_handle); NT_ERR(status, 1, "OpenService failed"); DEBUG(1, ("OpenService - %s\n", nt_errstr(status))); if (NT_STATUS_IS_OK(status)) { status = svc_ControlService(svc_pipe, &svc_handle, SERVICE_CONTROL_STOP, &svc_status); { struct SERVICE_STATUS s; do { msleep(100); status = svc_QueryServiceStatus(svc_pipe, &svc_handle, &s); NT_ERR(status, 1, "QueryServiceStatus failed"); } while (s.state == SERVICE_STOP_PENDING); if (s.state != SERVICE_STOPPED) { DEBUG(0, ("Service cannot stop, status=0x%08X\n", s.state)); return NT_STATUS_UNSUCCESSFUL; } } DEBUG(1, ("StopService - %s\n", nt_errstr(status))); status = svc_DeleteService(svc_pipe, &svc_handle); DEBUG(1, ("DeleteService - %s\n", nt_errstr(status))); status = svc_CloseServiceHandle(svc_pipe, &svc_handle); DEBUG(1, ("CloseServiceHandle - %s\n", nt_errstr(status))); } svc_CloseServiceHandle(svc_pipe, &scm_handle); DEBUG(1, ("CloseSCMHandle - %s\n", nt_errstr(status))); struct smbcli_state *cli; status = smbcli_full_connection(NULL, &cli, hostname, "ADMIN$", NULL, credentials, NULL); NT_ERR(status, 1, "Failed to open ADMIN$ share"); /* Give winexesvc some time to exit */ msleep(300); status = smbcli_unlink(cli->tree, "winexesvc.exe"); DEBUG(1, ("Delete winexesvc.exe - %s\n", nt_errstr(status))); status = smbcli_tdis(cli); DEBUG(1, ("Closing ADMIN$ - %s\n", nt_errstr(status))); return status; }
static NTSTATUS svc_UploadService(struct tevent_context *ev_ctx, const char *hostname, const char *service_filename, unsigned char *svc32_exe, unsigned int svc32_exe_len, unsigned char *svc64_exe, unsigned int svc64_exe_len, struct cli_credentials *credentials, struct loadparm_context *cllp_ctx, int flags) { struct smb_composite_savefile *io; struct smbcli_state *cli; NTSTATUS status; struct smbcli_options options; struct smbcli_session_options session_options; lpcfg_smbcli_options(cllp_ctx, &options); lpcfg_smbcli_session_options(cllp_ctx, &session_options); status = smbcli_full_connection(NULL, &cli, hostname, lpcfg_smb_ports(cllp_ctx), "ADMIN$", NULL, lpcfg_socket_options(cllp_ctx), credentials, lpcfg_resolve_context(cllp_ctx), ev_ctx, &options, &session_options, lpcfg_gensec_settings(NULL, cllp_ctx)); NT_ERR(status, 1, "Failed to open ADMIN$ share"); if (flags & SVC_FORCE_UPLOAD) { smbcli_unlink(cli->tree, service_filename); } else { int fd = smbcli_open(cli->tree, service_filename, O_RDONLY, DENY_NONE); if (fd >= 0) { smbcli_close(cli->tree, fd); return status; } } io = talloc_zero(cli->tree, struct smb_composite_savefile); io->in.fname = service_filename; if (flags & SVC_OSCHOOSE) { status = smbcli_chkpath(cli->tree, "SysWoW64"); } if (((flags & SVC_OSCHOOSE) && NT_STATUS_IS_OK(status)) || (flags & SVC_OS64BIT)) { DEBUG(1, ("svc_UploadService: Installing 64bit %s\n", service_filename)); io->in.data = svc64_exe; io->in.size = svc64_exe_len; } else { DEBUG(1, ("svc_UploadService: Installing 32bit %s\n", service_filename)); io->in.data = svc32_exe; io->in.size = svc32_exe_len; } status = smb_composite_savefile(cli->tree, io); NT_ERR(status, 1, "Failed to save ADMIN$/%s", io->in.fname); talloc_free(io); smbcli_tdis(cli); return status; }
static void testpair(TALLOC_CTX *mem_ctx, struct smbcli_state *cli, char *mask, char *file) { int fnum; char res1[256]; char *res2; static int count; char *short_name = NULL; char *long_name = NULL; struct masktest_state state; count++; safe_strcpy(res1, "---", sizeof(res1)); state.mem_ctx = mem_ctx; fnum = smbcli_open(cli->tree, file, O_CREAT|O_TRUNC|O_RDWR, 0); if (fnum == -1) { DEBUG(0,("Can't create %s\n", file)); return; } smbcli_close(cli->tree, fnum); resultp = res1; short_name = talloc_strdup(mem_ctx, ""); get_real_name(mem_ctx, cli, &long_name, &short_name); safe_strcpy(res1, "---", sizeof(res1)); smbcli_list_new(cli->tree, mask, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, listfn, &state); res2 = reg_test(cli, mem_ctx, mask, long_name, short_name); if (showall || strcmp(res1, res2)) { d_printf("%s %s %d mask=[%s] file=[%s] rfile=[%s/%s]\n", res1, res2, count, mask, file, long_name, short_name); if (die_on_error) exit(1); } smbcli_unlink(cli->tree, file); if (count % 100 == 0) DEBUG(0,("%d\n", count)); resultp = NULL; }
static void close_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES]) { int server, conn, f; for (server=0;server<NSERVERS;server++) for (conn=0;conn<NCONNECTIONS;conn++) for (f=0;f<NFILES;f++) { if (fnum[server][conn][f] != -1) { smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]); fnum[server][conn][f] = -1; } } for (server=0;server<NSERVERS;server++) { smbcli_unlink(cli[server][0]->tree, FILENAME); } }
BOOL torture_mangle(struct torture_context *torture, struct smbcli_state *cli) { extern int torture_numops; int i; /* we will use an internal tdb to store the names we have used */ tdb = tdb_open(NULL, 100000, TDB_INTERNAL, 0, 0); if (!tdb) { printf("ERROR: Failed to open tdb\n"); return False; } if (!torture_setup_dir(cli, "\\mangle_test")) { return False; } for (i=0;i<torture_numops;i++) { fstring name; ZERO_STRUCT(name); gen_name(name); if (!test_one(cli, name)) { break; } if (total && total % 100 == 0) { printf("collisions %u/%u - %.2f%% (%u failures)\r", collisions, total, (100.0*collisions) / total, failures); } } smbcli_unlink(cli->tree, "\\mangle_test\\*"); if (NT_STATUS_IS_ERR(smbcli_rmdir(cli->tree, "\\mangle_test"))) { printf("ERROR: Failed to remove directory\n"); return False; } printf("\nTotal collisions %u/%u - %.2f%% (%u failures)\n", collisions, total, (100.0*collisions) / total, failures); return (failures == 0); }
static void close_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], char *nfs[NSERVERS], int fnum[NSERVERS][NUMFSTYPES][NCONNECTIONS][NFILES]) { int server, conn, f, fstype; for (server=0;server<NSERVERS;server++) for (fstype=0;fstype<NUMFSTYPES;fstype++) for (conn=0;conn<NCONNECTIONS;conn++) for (f=0;f<NFILES;f++) { if (fnum[server][fstype][conn][f] != -1) { try_close(cli[server][conn], fstype, fnum[server][fstype][conn][f]); fnum[server][fstype][conn][f] = -1; } } for (server=0;server<NSERVERS;server++) { smbcli_unlink(cli[server][0], FILENAME); } }
/* test directory listing speed */ bool torture_dirtest1(struct torture_context *tctx, struct smbcli_state *cli) { int i; int fnum; bool correct = true; extern int torture_numops; struct timeval tv; torture_comment(tctx, "Creating %d random filenames\n", torture_numops); srandom(0); tv = timeval_current(); for (i=0;i<torture_numops;i++) { char *fname; asprintf(&fname, "\\%x", (int)random()); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { fprintf(stderr,"(%s) Failed to open %s\n", __location__, fname); return false; } smbcli_close(cli->tree, fnum); free(fname); } torture_comment(tctx, "Matched %d\n", smbcli_list(cli->tree, "a*.*", 0, list_fn, NULL)); torture_comment(tctx, "Matched %d\n", smbcli_list(cli->tree, "b*.*", 0, list_fn, NULL)); torture_comment(tctx, "Matched %d\n", smbcli_list(cli->tree, "xyzabc", 0, list_fn, NULL)); torture_comment(tctx, "dirtest core %g seconds\n", timeval_elapsed(&tv)); srandom(0); for (i=0;i<torture_numops;i++) { char *fname; asprintf(&fname, "\\%x", (int)random()); smbcli_unlink(cli->tree, fname); free(fname); } return correct; }
/* basic testing of all RAW_FILEINFO_* calls for each call we test that it succeeds, and where possible test for consistency between the calls. */ bool torture_raw_qfileinfo(struct torture_context *torture, struct smbcli_state *cli) { int fnum; bool ret; const char *fname = "\\torture_qfileinfo.txt"; fnum = create_complex_file(cli, torture, fname); if (fnum == -1) { printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); return false; } ret = torture_raw_qfileinfo_internals(torture, torture, cli->tree, fnum, fname, false /* is_ipc */); smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, fname); return ret; }
/* sees what IOCTLs are supported */ bool torture_ioctl_test(struct torture_context *tctx, struct smbcli_state *cli) { uint16_t device, function; int fnum; const char *fname = "\\ioctl.dat"; NTSTATUS status; union smb_ioctl parms; TALLOC_CTX *mem_ctx; mem_ctx = talloc_named_const(tctx, 0, "ioctl_test"); smbcli_unlink(cli->tree, fname); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum == -1) { torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); return false; } parms.ioctl.level = RAW_IOCTL_IOCTL; parms.ioctl.in.file.fnum = fnum; parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO; status = smb_raw_ioctl(cli->tree, mem_ctx, &parms); torture_comment(tctx, "ioctl job info: %s\n", smbcli_errstr(cli->tree)); for (device=0;device<0x100;device++) { torture_comment(tctx, "testing device=0x%x\n", device); for (function=0;function<0x100;function++) { parms.ioctl.in.request = (device << 16) | function; status = smb_raw_ioctl(cli->tree, mem_ctx, &parms); if (NT_STATUS_IS_OK(status)) { torture_comment(tctx, "ioctl device=0x%x function=0x%x OK : %d bytes\n", device, function, (int)parms.ioctl.out.blob.length); } } } return true; }
/** sometimes we need a fairly complex file to work with, so we can test all possible attributes. */ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname) { int fnum; char buf[7] = "abc"; union smb_setfileinfo setfile; union smb_fileinfo fileinfo; time_t t = (time(NULL) & ~1); NTSTATUS status; smbcli_unlink(cli->tree, fname); fnum = smbcli_nt_create_full(cli->tree, fname, 0, SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_DELETE| NTCREATEX_SHARE_ACCESS_READ| NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0); if (fnum == -1) return -1; smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)); if (strchr(fname, ':') == NULL) { /* setup some EAs */ setfile.generic.level = RAW_SFILEINFO_EA_SET; setfile.generic.in.file.fnum = fnum; setfile.ea_set.in.num_eas = 2; setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2); setfile.ea_set.in.eas[0].flags = 0; setfile.ea_set.in.eas[0].name.s = "EAONE"; setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6); setfile.ea_set.in.eas[1].flags = 0; setfile.ea_set.in.eas[1].name.s = "SECONDEA"; setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8); status = smb_raw_setfileinfo(cli->tree, &setfile); if (!NT_STATUS_IS_OK(status)) { printf("Failed to setup EAs\n"); } }
/* Test rename on files open with share delete and no share delete. */ bool torture_test_rename(struct torture_context *tctx, struct smbcli_state *cli1) { const char *fname = "\\test.txt"; const char *fname1 = "\\test1.txt"; int fnum1; smbcli_unlink(cli1->tree, fname); smbcli_unlink(cli1->tree, fname1); fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0); torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "First open failed - %s", smbcli_errstr(cli1->tree))); torture_assert(tctx, NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1)), "First rename succeeded - this should have failed !"); torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), talloc_asprintf(tctx, "close - 1 failed (%s)", smbcli_errstr(cli1->tree))); smbcli_unlink(cli1->tree, fname); smbcli_unlink(cli1->tree, fname1); fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0); torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "Second open failed - %s", smbcli_errstr(cli1->tree))); torture_assert_ntstatus_ok(tctx, smbcli_rename(cli1->tree, fname, fname1), talloc_asprintf(tctx, "Second rename failed - this should have succeeded - %s", smbcli_errstr(cli1->tree))); torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree))); smbcli_unlink(cli1->tree, fname); smbcli_unlink(cli1->tree, fname1); fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_READ_CONTROL, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0); torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "Third open failed - %s", smbcli_errstr(cli1->tree))); torture_assert_ntstatus_ok(tctx, smbcli_rename(cli1->tree, fname, fname1), talloc_asprintf(tctx, "Third rename failed - this should have succeeded - %s", smbcli_errstr(cli1->tree))); torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), talloc_asprintf(tctx, "close - 3 failed (%s)", smbcli_errstr(cli1->tree))); smbcli_unlink(cli1->tree, fname); smbcli_unlink(cli1->tree, fname1); return true; }
/**************************************************************************** check for existance of a nttrans call ****************************************************************************/ static bool scan_nttrans(struct smbcli_state *cli, int op, int level, int fnum, int dnum, const char *fname) { int data_len = 0; int param_len = 0; int rparam_len, rdata_len; uint8_t *param, *data; NTSTATUS status; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("scan_nttrans"); param = talloc_array(mem_ctx, uint8_t, PARAM_SIZE); data = talloc_array(mem_ctx, uint8_t, PARAM_SIZE); memset(data, 0, PARAM_SIZE); data_len = 4; /* try with a info level only */ param_len = 2; SSVAL(param, 0, level); status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a file descriptor */ param_len = 6; SSVAL(param, 0, fnum); SSVAL(param, 2, level); SSVAL(param, 4, 0); status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a notify style */ param_len = 6; SSVAL(param, 0, dnum); SSVAL(param, 2, dnum); SSVAL(param, 4, level); status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a file name */ param_len = 6; SSVAL(param, 0, level); SSVAL(param, 2, 0); SSVAL(param, 4, 0); param_len += push_string( ¶m[6], fname, PARAM_SIZE, STR_TERMINATE | STR_UNICODE); status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a new file name */ param_len = 6; SSVAL(param, 0, level); SSVAL(param, 2, 0); SSVAL(param, 4, 0); param_len += push_string( ¶m[6], "\\newfile.dat", PARAM_SIZE, STR_TERMINATE | STR_UNICODE); status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); smbcli_unlink(cli->tree, "\\newfile.dat"); smbcli_rmdir(cli->tree, "\\newfile.dat"); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try dfs style */ smbcli_mkdir(cli->tree, "\\testdir"); param_len = 2; SSVAL(param, 0, level); param_len += push_string(¶m[2], "\\testdir", PARAM_SIZE, STR_TERMINATE | STR_UNICODE); status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); smbcli_rmdir(cli->tree, "\\testdir"); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } talloc_free(mem_ctx); return false; }
bool unix_torture_unix_info2(struct torture_context *torture) { void *mem_ctx; struct smbcli_state *cli; int fnum; struct unix_info2 pinfo, finfo; mem_ctx = talloc_init("smb_query_unix_info2"); torture_assert(torture, mem_ctx != NULL, "out of memory"); if (!(cli = connect_to_server(torture))) { talloc_free(mem_ctx); return false; } smbcli_unlink(cli->tree, FILENAME); fnum = create_file(cli, FILENAME); torture_assert(torture, fnum != -1, smbcli_errstr(cli->tree)); printf("checking SMB_QFILEINFO_UNIX_INFO2 for QueryFileInfo\n"); if (!query_file_info2(mem_ctx, torture, cli, fnum, &finfo)) { goto fail; } printf("checking SMB_QFILEINFO_UNIX_INFO2 for QueryPathInfo\n"); if (!query_path_info2(mem_ctx, torture, cli, FILENAME, &pinfo)) { goto fail; } if (!match_info2(torture, &pinfo, &finfo)) { goto fail; } printf("checking SMB_FIND_UNIX_INFO2 for FindFirst\n"); if (!find_single_info2(mem_ctx, torture, cli, FILENAME, &pinfo)) { goto fail; } if (!match_info2(torture, &pinfo, &finfo)) { goto fail; } /* XXX: should repeat this test with SetFileInfo. */ printf("checking SMB_SFILEINFO_UNIX_INFO2 for SetPathInfo\n"); if (!verify_setinfo_flags(mem_ctx, torture, cli, FILENAME)) { goto fail; } smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, FILENAME); torture_close_connection(cli); talloc_free(mem_ctx); return true; fail: smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, FILENAME); torture_close_connection(cli); talloc_free(mem_ctx); return false; }
static bool torture_raw_sfileinfo_archive(struct torture_context *tctx, struct smbcli_state *cli) { const char *fname = BASEDIR "\\test_archive.dat"; NTSTATUS status; bool ret = true; union smb_open io; union smb_setfileinfo sfinfo; union smb_fileinfo finfo; uint16_t fnum=0; if (!torture_setup_dir(cli, BASEDIR)) { return false; } /* cleanup */ smbcli_unlink(cli->tree, fname); /* * create a normal file, verify archive bit */ io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; 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_CREATE; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; io.ntcreatex.in.flags = 0; status = smb_raw_open(cli->tree, tctx, &io); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "open failed"); fnum = io.ntcreatex.out.file.fnum; torture_assert_int_equal(tctx, io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, FILE_ATTRIBUTE_ARCHIVE, "archive bit not set"); /* * try to turn off archive bit */ ZERO_STRUCT(sfinfo); sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO; sfinfo.generic.in.file.fnum = fnum; sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL; status = smb_raw_setfileinfo(cli->tree, &sfinfo); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "setfileinfo failed"); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, tctx, &finfo); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "fileinfo failed"); torture_assert_int_equal(tctx, finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, FILE_ATTRIBUTE_NORMAL, "archive bit set"); status = smbcli_close(cli->tree, fnum); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "close failed"); status = smbcli_unlink(cli->tree, fname); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "unlink failed"); /* * create a directory, verify no archive bit */ io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.access_mask = SEC_RIGHTS_DIR_ALL; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; io.ntcreatex.in.flags = 0; status = smb_raw_open(cli->tree, tctx, &io); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "directory open failed"); fnum = io.ntcreatex.out.file.fnum; torture_assert_int_equal(tctx, io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, FILE_ATTRIBUTE_DIRECTORY, "archive bit set"); /* * verify you can turn on archive bit */ sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO; sfinfo.generic.in.file.fnum = fnum; sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE; status = smb_raw_setfileinfo(cli->tree, &sfinfo); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "setfileinfo failed"); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, tctx, &finfo); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "fileinfo failed"); torture_assert_int_equal(tctx, finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE, "archive bit not set"); /* * and try to turn it back off */ sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO; sfinfo.generic.in.file.fnum = fnum; sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY; status = smb_raw_setfileinfo(cli->tree, &sfinfo); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "setfileinfo failed"); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, tctx, &finfo); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "fileinfo failed"); torture_assert_int_equal(tctx, finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, FILE_ATTRIBUTE_DIRECTORY, "archive bit set"); status = smbcli_close(cli->tree, fnum); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "close failed"); done: smbcli_close(cli->tree, fnum); smbcli_deltree(cli->tree, BASEDIR); return ret; }
static bool torture_raw_sfileinfo_eof_access(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) { const char *fname = BASEDIR "\\test_exclusive3.dat"; NTSTATUS status, expected_status; bool ret = true; union smb_open io; union smb_setfileinfo sfi; uint16_t fnum=0; uint32_t access_mask = 0; if (!torture_setup_dir(cli1, BASEDIR)) { return false; } /* cleanup */ smbcli_unlink(cli1->tree, fname); /* * base ntcreatex parms */ io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid.fnum = 0; 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_OVERWRITE_IF; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; io.ntcreatex.in.flags = 0; for (access_mask = 1; access_mask <= 0x00001FF; access_mask++) { io.ntcreatex.in.access_mask = access_mask; status = smb_raw_open(cli1->tree, tctx, &io); if (!NT_STATUS_IS_OK(status)) { continue; } fnum = io.ntcreatex.out.file.fnum; ZERO_STRUCT(sfi); sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO; sfi.generic.in.file.fnum = fnum; sfi.end_of_file_info.in.size = 100; status = smb_raw_setfileinfo(cli1->tree, &sfi); expected_status = (access_mask & SEC_FILE_WRITE_DATA) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED; if (!NT_STATUS_EQUAL(expected_status, status)) { torture_comment(tctx, "0x%x wrong\n", access_mask); } torture_assert_ntstatus_equal_goto(tctx, status, expected_status, ret, done, "Status Wrong"); smbcli_close(cli1->tree, fnum); } done: smb_raw_exit(cli1->session); smb_raw_exit(cli2->session); smbcli_deltree(cli1->tree, BASEDIR); return ret; }
/** * Test both the snia cifs RAW_SFILEINFO_END_OF_FILE_INFO and the undocumented * pass-through RAW_SFILEINFO_END_OF_FILE_INFORMATION in the context of * trans2setpathinfo. */ static bool torture_raw_sfileinfo_eof(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) { const char *fname = BASEDIR "\\test_sfileinfo_end_of_file.dat"; NTSTATUS status; bool ret = true; union smb_open io; union smb_setfileinfo sfi; union smb_fileinfo qfi; uint16_t fnum = 0; if (!torture_setup_dir(cli1, BASEDIR)) { return false; } /* cleanup */ smbcli_unlink(cli1->tree, fname); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; 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.security_flags = 0; io.ntcreatex.in.fname = fname; io.ntcreatex.in.flags = 0; /* Open the file sharing none. */ status = smb_raw_open(cli1->tree, tctx, &io); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); fnum = io.ntcreatex.out.file.fnum; /* Try to sfileinfo to extend the file. */ ZERO_STRUCT(sfi); sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO; sfi.generic.in.file.path = fname; sfi.end_of_file_info.in.size = 100; status = smb_raw_setpathinfo(cli2->tree, &sfi); /* There should be share mode contention in this case. */ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be " "SHARING_VIOLATION"); /* Make sure the size is still 0. */ ZERO_STRUCT(qfi); qfi.generic.level = RAW_FILEINFO_STANDARD_INFO; qfi.generic.in.file.path = fname; status = smb_raw_pathinfo(cli2->tree, tctx, &qfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 0, "alloc_size should be 0 since the setpathinfo failed."); /* Try again with the pass through instead of documented version. */ ZERO_STRUCT(sfi); sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; sfi.generic.in.file.path = fname; sfi.end_of_file_info.in.size = 100; status = smb_raw_setpathinfo(cli2->tree, &sfi); /* * Looks like a windows bug: * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html */ if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) { /* It succeeds! This is just weird! */ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); /* Verify that the file was actually extended to 100. */ ZERO_STRUCT(qfi); qfi.generic.level = RAW_FILEINFO_STANDARD_INFO; qfi.generic.in.file.path = fname; status = smb_raw_pathinfo(cli2->tree, tctx, &qfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 100, "alloc_size should be 100 since the setpathinfo " "succeeded."); } else { torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be " "SHARING_VIOLATION"); } /* close the first file. */ smbcli_close(cli1->tree, fnum); fnum = 0; /* Try to sfileinfo to extend the file again (non-pass-through). */ ZERO_STRUCT(sfi); sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO; sfi.generic.in.file.path = fname; sfi.end_of_file_info.in.size = 200; status = smb_raw_setpathinfo(cli2->tree, &sfi); /* This should cause the client to retun invalid level. */ if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) { /* * Windows sends back an invalid packet that smbclient sees * and returns INTERNAL_ERROR. */ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INTERNAL_ERROR, ret, done, "Status should be " "INTERNAL_ERROR"); } else { torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INVALID_LEVEL, ret, done, "Status should be " "INVALID_LEVEL"); } /* Try to extend the file now with the passthrough level. */ sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; status = smb_raw_setpathinfo(cli2->tree, &sfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); /* Verify that the file was actually extended to 200. */ ZERO_STRUCT(qfi); qfi.generic.level = RAW_FILEINFO_STANDARD_INFO; qfi.generic.in.file.path = fname; status = smb_raw_pathinfo(cli2->tree, tctx, &qfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 200, "alloc_size should be 200 since the setpathinfo succeeded."); /* Open the file so end of file can be set by handle. */ io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE; status = smb_raw_open(cli1->tree, tctx, &io); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); fnum = io.ntcreatex.out.file.fnum; /* Try sfileinfo to extend the file by handle (non-pass-through). */ ZERO_STRUCT(sfi); sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO; sfi.generic.in.file.fnum = fnum; sfi.end_of_file_info.in.size = 300; status = smb_raw_setfileinfo(cli1->tree, &sfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); /* Verify that the file was actually extended to 300. */ ZERO_STRUCT(qfi); qfi.generic.level = RAW_FILEINFO_STANDARD_INFO; qfi.generic.in.file.path = fname; status = smb_raw_pathinfo(cli1->tree, tctx, &qfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 300, "alloc_size should be 300 since the setpathinfo succeeded."); /* Try sfileinfo to extend the file by handle (pass-through). */ ZERO_STRUCT(sfi); sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; sfi.generic.in.file.fnum = fnum; sfi.end_of_file_info.in.size = 400; status = smb_raw_setfileinfo(cli1->tree, &sfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); /* Verify that the file was actually extended to 300. */ ZERO_STRUCT(qfi); qfi.generic.level = RAW_FILEINFO_STANDARD_INFO; qfi.generic.in.file.path = fname; status = smb_raw_pathinfo(cli1->tree, tctx, &qfi); torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret, done, "Status should be OK"); torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 400, "alloc_size should be 400 since the setpathinfo succeeded."); done: if (fnum > 0) { smbcli_close(cli1->tree, fnum); fnum = 0; } smb_raw_exit(cli1->session); smb_raw_exit(cli2->session); smbcli_deltree(cli1->tree, BASEDIR); return ret; }
/* test SMBntrename ops */ static bool test_ntrename(struct torture_context *tctx, struct smbcli_state *cli) { union smb_rename io; NTSTATUS status; bool ret = true; int fnum, i; const char *fname1 = BASEDIR "\\test1.txt"; const char *fname2 = BASEDIR "\\test2.txt"; union smb_fileinfo finfo; torture_comment(tctx, "Testing SMBntrename\n"); if (!torture_setup_dir(cli, BASEDIR)) { return false; } torture_comment(tctx, "Trying simple rename\n"); fnum = create_complex_file(cli, tctx, fname1); io.generic.level = RAW_RENAME_NTRENAME; io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.cluster_size = 0; io.ntrename.in.flags = RENAME_FLAG_RENAME; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); smbcli_close(cli->tree, fnum); status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "Trying self rename\n"); io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname2; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname1; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); torture_comment(tctx, "trying wildcard rename\n"); io.ntrename.in.old_name = BASEDIR "\\*.txt"; io.ntrename.in.new_name = fname1; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); torture_comment(tctx, "Checking attrib handling\n"); torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN); io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname1; io.ntrename.in.attrib = 0; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE); io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL); torture_comment(tctx, "Checking hard link\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_HARD_LINK; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname2; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 2); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 2); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL); smbcli_unlink(cli->tree, fname2); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); torture_comment(tctx, "Checking copy\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_COPY; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname2; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname2; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL); smbcli_unlink(cli->tree, fname2); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); torture_comment(tctx, "Checking invalid flags\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = 0; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } io.ntrename.in.flags = 300; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } io.ntrename.in.flags = 0x106; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "Checking unknown field\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_RENAME; io.ntrename.in.cluster_size = 0xff; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n"); io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname1; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION; io.ntrename.in.cluster_size = 1; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); io.ntrename.in.flags = RENAME_FLAG_COPY; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); #if 0 { char buf[16384]; fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE); memset(buf, 1, sizeof(buf)); smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)); smbcli_close(cli->tree, fnum); fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE); memset(buf, 1, sizeof(buf)); smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1); smbcli_close(cli->tree, fnum); torture_all_info(cli->tree, fname1); torture_all_info(cli->tree, fname2); } io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); for (i=0; i<20000; i++) { io.ntrename.in.cluster_size = i; status = smb_raw_rename(cli->tree, &io); if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { torture_warning(tctx, "i=%d status=%s\n", i, nt_errstr(status)); } } #endif torture_comment(tctx, "Checking other flags\n"); for (i=0; i<0xFFF; i++) { if (i == RENAME_FLAG_RENAME || i == RENAME_FLAG_HARD_LINK || i == RENAME_FLAG_COPY) { continue; } io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname1; io.ntrename.in.flags = i; io.ntrename.in.attrib = 0; io.ntrename.in.cluster_size = 0; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { torture_warning(tctx, "flags=0x%x status=%s\n", i, nt_errstr(status)); } } else { if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { torture_warning(tctx, "flags=0x%x status=%s\n", i, nt_errstr(status)); } } } done: smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); return ret; }
/* test dir rename. */ static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli) { union smb_open io; union smb_rename ren_io; NTSTATUS status; const char *dname1 = BASEDIR "\\dir_for_rename"; const char *dname2 = BASEDIR "\\renamed_dir"; const char *dname1_long = BASEDIR "\\dir_for_rename_long"; const char *fname = BASEDIR "\\dir_for_rename\\file.txt"; const char *sname = BASEDIR "\\renamed_dir:a stream:$DATA"; bool ret = true; int fnum = -1; torture_comment(tctx, "Checking rename on a directory containing an open file.\n"); if (!torture_setup_dir(cli, BASEDIR)) { return false; } /* create a directory */ smbcli_rmdir(cli->tree, dname1); smbcli_rmdir(cli->tree, dname2); smbcli_rmdir(cli->tree, dname1_long); smbcli_unlink(cli->tree, dname1); smbcli_unlink(cli->tree, dname2); smbcli_unlink(cli->tree, dname1_long); ZERO_STRUCT(io); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; io.ntcreatex.in.fname = dname1; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; smbcli_close(cli->tree, fnum); /* create the longname directory */ io.ntcreatex.in.fname = dname1_long; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; smbcli_close(cli->tree, fnum); /* Now create and hold open a file. */ 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.alloc_size = 0; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; /* Create the file. */ status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; /* Now try and rename the directory. */ ZERO_STRUCT(ren_io); ren_io.generic.level = RAW_RENAME_RENAME; ren_io.rename.in.pattern1 = dname1; ren_io.rename.in.pattern2 = dname2; ren_io.rename.in.attrib = 0; status = smb_raw_rename(cli->tree, &ren_io); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); /* Close the file and try the rename. */ smbcli_close(cli->tree, fnum); status = smb_raw_rename(cli->tree, &ren_io); CHECK_STATUS(status, NT_STATUS_OK); /* * Now try just holding a second handle on the directory and holding * it open across a rename. This should be allowed. */ io.ntcreatex.in.fname = dname2; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; ren_io.generic.level = RAW_RENAME_RENAME; ren_io.rename.in.pattern1 = dname2; ren_io.rename.in.pattern2 = dname1; ren_io.rename.in.attrib = 0; status = smb_raw_rename(cli->tree, &ren_io); CHECK_STATUS(status, NT_STATUS_OK); /* close our handle to the directory. */ smbcli_close(cli->tree, fnum); /* Open a handle on the long name, and then * try a rename. This would catch a regression * in bug #6781. */ io.ntcreatex.in.fname = dname1_long; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; ren_io.generic.level = RAW_RENAME_RENAME; ren_io.rename.in.pattern1 = dname1; ren_io.rename.in.pattern2 = dname2; ren_io.rename.in.attrib = 0; status = smb_raw_rename(cli->tree, &ren_io); CHECK_STATUS(status, NT_STATUS_OK); /* close our handle to the longname directory. */ smbcli_close(cli->tree, fnum); /* * Now try opening a stream on the directory and holding it open * across a rename. This should be allowed. */ io.ntcreatex.in.fname = sname; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; ren_io.generic.level = RAW_RENAME_RENAME; ren_io.rename.in.pattern1 = dname2; ren_io.rename.in.pattern2 = dname1; ren_io.rename.in.attrib = 0; status = smb_raw_rename(cli->tree, &ren_io); CHECK_STATUS(status, NT_STATUS_OK); done: if (fnum != -1) { smbcli_close(cli->tree, fnum); } smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); return ret; }
/* basic testing of all RAW_SFILEINFO_* calls for each call we test that it succeeds, and where possible test for consistency between the calls. */ static bool torture_raw_sfileinfo_base(struct torture_context *torture, struct smbcli_state *cli) { bool ret = true; int fnum = -1; char *fnum_fname; char *fnum_fname_new; char *path_fname; char *path_fname_new; union smb_fileinfo finfo1, finfo2; union smb_setfileinfo sfinfo; NTSTATUS status, status2; const char *call_name; time_t basetime = (time(NULL) - 86400) & ~1; bool check_fnum; int n = time(NULL) % 100; asprintf(&path_fname, BASEDIR "\\fname_test_%d.txt", n); asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n); asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n); asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n); if (!torture_setup_dir(cli, BASEDIR)) { return false; } #define RECREATE_FILE(fname) do { \ if (fnum != -1) smbcli_close(cli->tree, fnum); \ fnum = create_complex_file(cli, torture, fname); \ if (fnum == -1) { \ printf("(%s) ERROR: open of %s failed (%s)\n", \ __location__, fname, smbcli_errstr(cli->tree)); \ ret = false; \ goto done; \ }} while (0) #define RECREATE_BOTH do { \ RECREATE_FILE(path_fname); \ smbcli_close(cli->tree, fnum); \ RECREATE_FILE(fnum_fname); \ } while (0) RECREATE_BOTH; #define CHECK_CALL_FNUM(call, rightstatus) do { \ check_fnum = true; \ call_name = #call; \ sfinfo.generic.level = RAW_SFILEINFO_ ## call; \ sfinfo.generic.in.file.fnum = fnum; \ status = smb_raw_setfileinfo(cli->tree, &sfinfo); \ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \ torture_warning(torture, \ "(%s) %s - %s", __location__, #call, \ nt_errstr(status)); \ } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \ printf("(%s) %s - %s (should be %s)\n", __location__, #call, \ nt_errstr(status), nt_errstr(rightstatus)); \ ret = false; \ } \ finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \ finfo1.generic.in.file.fnum = fnum; \ status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \ torture_warning(torture, \ "(%s) %s - %s", __location__, #call, \ nt_errstr(status)); \ } else if (!NT_STATUS_IS_OK(status2)) { \ printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \ ret = false; \ }} while (0) #define CHECK_CALL_PATH(call, rightstatus) do { \ check_fnum = false; \ call_name = #call; \ sfinfo.generic.level = RAW_SFILEINFO_ ## call; \ sfinfo.generic.in.file.path = path_fname; \ status = smb_raw_setpathinfo(cli->tree, &sfinfo); \ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \ sfinfo.generic.in.file.path = path_fname_new; \ status = smb_raw_setpathinfo(cli->tree, &sfinfo); \ } \ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \ torture_warning(torture, \ "(%s) %s - %s", __location__, #call, \ nt_errstr(status)); \ } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \ printf("(%s) %s - %s (should be %s)\n", __location__, #call, \ nt_errstr(status), nt_errstr(rightstatus)); \ ret = false; \ } \ finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \ finfo1.generic.in.file.path = path_fname; \ status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \ if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \ finfo1.generic.in.file.path = path_fname_new; \ status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \ } \ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \ torture_warning(torture, \ "(%s) %s - %s", __location__, #call, \ nt_errstr(status)); \ } else if (!NT_STATUS_IS_OK(status2)) { \ printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \ ret = false; \ }} while (0) #define CHECK1(call) \ do { if (NT_STATUS_IS_OK(status)) { \ finfo2.generic.level = RAW_FILEINFO_ ## call; \ if (check_fnum) { \ finfo2.generic.in.file.fnum = fnum; \ status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \ } else { \ finfo2.generic.in.file.path = path_fname; \ status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \ if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \ finfo2.generic.in.file.path = path_fname_new; \ status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \ } \ } \ if (!NT_STATUS_IS_OK(status2)) { \ printf("%s - %s\n", #call, nt_errstr(status2)); \ ret = false; \ } \ }} while (0) #define CHECK_VALUE(call, stype, field, value) do { \ CHECK1(call); \ if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \ printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \ call_name, #stype, #field, \ (unsigned int)value, (unsigned int)finfo2.stype.out.field); \ dump_all_info(torture, &finfo1); \ ret = false; \ }} while (0) #define CHECK_TIME(call, stype, field, value) do { \ CHECK1(call); \ if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \ printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \ call_name, #stype, #field, \ (unsigned int)value, \ (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \ printf("\t%s", timestring(torture, value)); \ printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \ dump_all_info(torture, &finfo1); \ ret = false; \ }} while (0) #define CHECK_STR(call, stype, field, value) do { \ CHECK1(call); \ if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \ printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \ call_name, #stype, #field, \ value, \ finfo2.stype.out.field); \ dump_all_info(torture, &finfo1); \ ret = false; \ }} while (0) #define CHECK_STATUS(status, correct) do { \ if (!NT_STATUS_EQUAL(status, correct)) { \ printf("(%s) Incorrect status %s - should be %s\n", \ __location__, nt_errstr(status), nt_errstr(correct)); \ ret = false; \ goto done; \ }} while (0) printf("Test setattr\n"); sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_READONLY; sfinfo.setattr.in.write_time = basetime; CHECK_CALL_PATH(SETATTR, NT_STATUS_OK); CHECK_VALUE (ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY); CHECK_TIME (ALL_INFO, all_info, write_time, basetime); printf("setting to NORMAL doesn't do anything\n"); sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_NORMAL; sfinfo.setattr.in.write_time = 0; CHECK_CALL_PATH(SETATTR, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY); CHECK_TIME (ALL_INFO, all_info, write_time, basetime); printf("a zero write_time means don't change\n"); sfinfo.setattr.in.attrib = 0; sfinfo.setattr.in.write_time = 0; CHECK_CALL_PATH(SETATTR, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL); CHECK_TIME (ALL_INFO, all_info, write_time, basetime); printf("Test setattre\n"); sfinfo.setattre.in.create_time = basetime + 20; sfinfo.setattre.in.access_time = basetime + 30; sfinfo.setattre.in.write_time = basetime + 40; CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 40); sfinfo.setattre.in.create_time = 0; sfinfo.setattre.in.access_time = 0; sfinfo.setattre.in.write_time = 0; CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 40); printf("Test standard level\n"); sfinfo.standard.in.create_time = basetime + 100; sfinfo.standard.in.access_time = basetime + 200; sfinfo.standard.in.write_time = basetime + 300; CHECK_CALL_FNUM(STANDARD, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300); printf("Test basic_info level\n"); basetime += 86400; unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100); unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200); unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300); unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY; CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300); CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400); CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY); printf("a zero time means don't change\n"); unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0); sfinfo.basic_info.in.attrib = 0; CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300); CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400); CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY); printf("Test basic_information level\n"); basetime += 86400; unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100); unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200); unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300); unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL; CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300); CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400); CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL); CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300); CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400); CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL); torture_comment(torture, "try to change a file to a directory\n"); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY; CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_INVALID_PARAMETER); printf("a zero time means don't change\n"); unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL; CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300); CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400); CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL); CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK); CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100); CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200); CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300); /* interesting - w2k3 leaves change_time as current time for 0 change time in setpathinfo CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400); */ CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL); printf("Test disposition_info level\n"); sfinfo.disposition_info.in.delete_on_close = 1; CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1); CHECK_VALUE(ALL_INFO, all_info, nlink, 0); sfinfo.disposition_info.in.delete_on_close = 0; CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0); CHECK_VALUE(ALL_INFO, all_info, nlink, 1); printf("Test disposition_information level\n"); sfinfo.disposition_info.in.delete_on_close = 1; CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1); CHECK_VALUE(ALL_INFO, all_info, nlink, 0); /* this would delete the file! */ /* CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1); CHECK_VALUE(ALL_INFO, all_info, nlink, 0); */ sfinfo.disposition_info.in.delete_on_close = 0; CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0); CHECK_VALUE(ALL_INFO, all_info, nlink, 1); CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0); CHECK_VALUE(ALL_INFO, all_info, nlink, 1); printf("Test allocation_info level\n"); sfinfo.allocation_info.in.alloc_size = 0; CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 0); CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0); sfinfo.allocation_info.in.alloc_size = 4096; CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096); CHECK_VALUE(ALL_INFO, all_info, size, 0); RECREATE_BOTH; sfinfo.allocation_info.in.alloc_size = 0; CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 0); CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0); CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 0); CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0); sfinfo.allocation_info.in.alloc_size = 4096; CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096); CHECK_VALUE(ALL_INFO, all_info, size, 0); /* setting the allocation size up via setpathinfo seems to be broken in w2k3 */ CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0); CHECK_VALUE(ALL_INFO, all_info, size, 0); printf("Test end_of_file_info level\n"); sfinfo.end_of_file_info.in.size = 37; CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 37); sfinfo.end_of_file_info.in.size = 7; CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 7); sfinfo.end_of_file_info.in.size = 37; CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 37); CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 37); sfinfo.end_of_file_info.in.size = 7; CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 7); CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(ALL_INFO, all_info, size, 7); printf("Test position_information level\n"); sfinfo.position_information.in.position = 123456; CHECK_CALL_FNUM(POSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456); CHECK_CALL_PATH(POSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(POSITION_INFORMATION, position_information, position, 0); printf("Test mode_information level\n"); sfinfo.mode_information.in.mode = 2; CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2); CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0); sfinfo.mode_information.in.mode = 1; CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER); CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER); sfinfo.mode_information.in.mode = 0; CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0); CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0); #if 0 printf("Test unix_basic level\n"); CHECK_CALL_FNUM(UNIX_BASIC, NT_STATUS_OK); CHECK_CALL_PATH(UNIX_BASIC, NT_STATUS_OK); printf("Test unix_link level\n"); CHECK_CALL_FNUM(UNIX_LINK, NT_STATUS_OK); CHECK_CALL_PATH(UNIX_LINK, NT_STATUS_OK); #endif done: smb_raw_exit(cli->session); smbcli_close(cli->tree, fnum); if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) { printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree)); } if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) { printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree)); } return ret; }