/* 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; }
/* basic testing of session/tree context calls */ static BOOL torture_raw_context_int(void) { struct smbcli_state *cli; BOOL ret = True; TALLOC_CTX *mem_ctx; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_raw_context"); ret &= test_session(cli, mem_ctx); ret &= test_tree(cli, mem_ctx); ret &= test_tree_ulogoff(cli, mem_ctx); ret &= test_pid_exit_only_sees_open(cli, mem_ctx); ret &= test_pid_2sess(cli, mem_ctx); ret &= test_pid_2tcon(cli, mem_ctx); smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
/* basic testing of streams calls */ BOOL torture_raw_streams(struct torture_context *torture) { struct smbcli_state *cli; BOOL ret = True; TALLOC_CTX *mem_ctx; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_raw_streams"); if (!torture_setup_dir(cli, BASEDIR)) { return False; } ret &= test_stream_io(cli, mem_ctx); smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
bool torture_samba3_caseinsensitive(struct torture_context *torture) { struct smbcli_state *cli; TALLOC_CTX *mem_ctx; NTSTATUS status; const char *dirname = "insensitive"; const char *ucase_dirname = "InSeNsItIvE"; const char *fname = "foo"; char *fpath; int fnum; int counter = 0; bool ret = true; if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) { d_printf("talloc_init failed\n"); return false; } if (!torture_open_connection(&cli, torture, 0)) { goto done; } smbcli_deltree(cli->tree, dirname); status = smbcli_mkdir(cli->tree, dirname); if (!NT_STATUS_IS_OK(status)) { d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status)); goto done; } if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) { goto done; } fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { d_printf("Could not create file %s: %s\n", fpath, smbcli_errstr(cli->tree)); goto done; } smbcli_close(cli->tree, fnum); smbcli_list(cli->tree, talloc_asprintf( mem_ctx, "%s\\*", ucase_dirname), FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN |FILE_ATTRIBUTE_SYSTEM, count_fn, (void *)&counter); if (counter == 3) { ret = true; } else { d_fprintf(stderr, "expected 3 entries, got %d\n", counter); ret = false; } done: talloc_free(mem_ctx); return ret; }
/* run a test that simulates an approximate netbench client load */ bool torture_nbench(struct torture_context *torture) { bool correct = true; int torture_nprocs = torture_setting_int(torture, "nprocs", 4); struct smbcli_state *cli; const char *p; read_only = torture_setting_bool(torture, "readonly", false); nb_max_retries = torture_setting_int(torture, "nretries", 1); p = torture_setting_string(torture, "timelimit", NULL); if (p && *p) { timelimit = atoi(p); } warmup = timelimit / 20; loadfile = torture_setting_string(torture, "loadfile", NULL); if (!loadfile || !*loadfile) { loadfile = "client.txt"; } if (torture_nprocs > 1) { if (!torture_open_connection(&cli, torture, 0)) { return false; } if (!read_only && !torture_setup_dir(cli, "\\clients")) { return false; } } nbio_shmem(torture_nprocs, timelimit, warmup); printf("Running for %d seconds with load '%s' and warmup %d secs\n", timelimit, loadfile, warmup); /* we need to reset SIGCHLD here as the name resolution library may have changed it. We rely on correct signals from childs in the main torture code which reaps children. This is why smbtorture BENCH-NBENCH was sometimes failing */ signal(SIGCHLD, SIG_DFL); signal(SIGALRM, nb_alarm); alarm(1); torture_create_procs(torture, run_netbench, &correct); alarm(0); if (!read_only && torture_nprocs > 1) { smbcli_deltree(cli->tree, "\\clients"); } printf("\nThroughput %g MB/sec\n", nbio_result()); return correct; }
/* basic testing of disconnects */ bool torture_disconnect(struct torture_context *torture) { bool ret = true; TALLOC_CTX *mem_ctx; int i; extern int torture_numops; struct smbcli_state *cli; mem_ctx = talloc_init("torture_raw_mux"); if (!torture_open_connection(&cli, torture, 0)) { return false; } if (!torture_setup_dir(cli, BASEDIR)) { return false; } for (i=0;i<torture_numops;i++) { ret &= test_disconnect_lock(cli, mem_ctx); if (!torture_open_connection(&cli, torture, 0)) { return false; } ret &= test_disconnect_open(cli, mem_ctx); if (!torture_open_connection(&cli, torture, 0)) { return false; } if (torture_setting_bool(torture, "samba3", false)) { /* * In Samba3 it might happen that the old smbd from * test_disconnect_lock is not scheduled before the * new process comes in. Try to get rid of the random * failures in the build farm. */ smb_msleep(200); } } smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); talloc_free(mem_ctx); return ret; }
bool torture_mangle(int dummy) { static struct cli_state *cli; int i; bool ret = True; printf("starting mangle test\n"); if (!torture_open_connection(&cli, 0)) { return False; } /* 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; } cli_unlink(cli, "\\mangle_test\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); cli_rmdir(cli, "\\mangle_test"); if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\mangle_test"))) { printf("ERROR: Failed to make directory\n"); return False; } for (i=0;i<torture_numops;i++) { fstring name; ZERO_STRUCT(name); gen_name(name); if (!test_one(cli, name)) { ret = False; break; } if (total && total % 100 == 0) { printf("collisions %u/%u - %.2f%% (%u failures)\r", collisions, total, (100.0*collisions) / total, failures); } } cli_unlink(cli, "\\mangle_test\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); if (!NT_STATUS_IS_OK(cli_rmdir(cli, "\\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); torture_close_connection(cli); printf("mangle test finished\n"); return (ret && (failures == 0)); }
bool run_cleanup1(int dummy) { struct cli_state *cli; const char *fname = "\\cleanup1"; uint16_t fnum; NTSTATUS status; printf("CLEANUP1: Checking that a conflicting share mode is cleaned " "up\n"); if (!torture_open_connection(&cli, 0)) { return false; } status = cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_ALL, &fnum); if (!NT_STATUS_IS_OK(status)) { printf("open of %s failed (%s)\n", fname, nt_errstr(status)); return false; } status = smbXcli_conn_samba_suicide(cli->conn, 1); if (!NT_STATUS_IS_OK(status)) { printf("smbXcli_conn_samba_suicide failed: %s\n", nt_errstr(status)); return false; } if (!torture_open_connection(&cli, 1)) { return false; } status = cli_ntcreate( cli, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, FILE_DELETE_ON_CLOSE, 0, &fnum, NULL); if (!NT_STATUS_IS_OK(status)) { printf("2nd open of %s failed (%s)\n", fname, nt_errstr(status)); return false; } cli_close(cli, fnum); torture_close_connection(cli); return NT_STATUS_IS_OK(status); }
/* scan for valid base SMB requests */ bool torture_smb_scan(struct torture_context *torture) { static struct smbcli_state *cli; int op; struct smbcli_request *req; NTSTATUS status; for (op=0x0;op<=0xFF;op++) { if (op == SMBreadbraw) continue; if (!torture_open_connection(&cli, torture, 0)) { return false; } req = smbcli_request_setup(cli->tree, op, 0, 0); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); break; } usleep(10000); smbcli_transport_process(cli->transport); if (req->state > SMBCLI_REQUEST_RECV) { status = smbcli_request_simple_recv(req); printf("op=0x%x status=%s\n", op, nt_errstr(status)); torture_close_connection(cli); continue; } sleep(1); smbcli_transport_process(cli->transport); if (req->state > SMBCLI_REQUEST_RECV) { status = smbcli_request_simple_recv(req); printf("op=0x%x status=%s\n", op, nt_errstr(status)); } else { printf("op=0x%x no reply\n", op); smbcli_request_destroy(req); continue; /* don't attempt close! */ } torture_close_connection(cli); } printf("smb scan finished\n"); return true; }
/* open N connections to the server and just hold them open used for testing performance when there are N idle users already connected */ bool torture_holdcon(struct torture_context *tctx) { int i; struct smbcli_state **cli; int num_dead = 0; torture_comment(tctx, "Opening %d connections\n", torture_numops); cli = malloc_array_p(struct smbcli_state *, torture_numops); for (i=0;i<torture_numops;i++) { if (!torture_open_connection(&cli[i], tctx, i)) { return false; } if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "opened %d connections\r", i); fflush(stdout); } } torture_comment(tctx, "\nStarting pings\n"); while (1) { for (i=0;i<torture_numops;i++) { NTSTATUS status; if (cli[i]) { status = smbcli_chkpath(cli[i]->tree, "\\"); if (!NT_STATUS_IS_OK(status)) { torture_comment(tctx, "Connection %d is dead\n", i); cli[i] = NULL; num_dead++; } usleep(100); } } if (num_dead == torture_numops) { torture_comment(tctx, "All connections dead - finishing\n"); break; } torture_comment(tctx, "."); fflush(stdout); } return true; }
static bool create_stale_share_mode_entry(const char *fname, struct file_id *p_id) { struct cli_state *cli; uint16_t fnum; NTSTATUS status; SMB_STRUCT_STAT sbuf; struct file_id id; if (!torture_open_connection(&cli, 0)) { return false; } status = torture_setup_unix_extensions(cli); if (!NT_STATUS_IS_OK(status)) { printf("torture_setup_unix_extensions failed: %s\n", nt_errstr(status)); return false; } status = cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_ALL, &fnum); if (!NT_STATUS_IS_OK(status)) { printf("open of %s failed (%s)\n", fname, nt_errstr(status)); return false; } status = cli_posix_stat(cli, fname, &sbuf); if (!NT_STATUS_IS_OK(status)) { printf("cli_posix_stat failed: %s\n", nt_errstr(status)); return false; } status = smbXcli_conn_samba_suicide(cli->conn, 1); if (!NT_STATUS_IS_OK(status)) { printf("smbXcli_conn_samba_suicide failed: %s\n", nt_errstr(status)); return false; } id.devid = sbuf.st_ex_rdev; id.inode = sbuf.st_ex_ino; id.extid = 0; poll(NULL, 0, 1000); *p_id = id; return true; }
bool torture_trans2_scan(int dummy) { static struct cli_state *cli; int op, level; const char *fname = "\\scanner.dat"; uint16_t fnum, dnum; printf("starting trans2 scan test\n"); if (!torture_open_connection(&cli, 0)) { return False; } if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum))) { printf("open of %s failed\n", fname); return false; } if (!NT_STATUS_IS_OK(cli_open(cli, "\\", O_RDONLY, DENY_NONE, &dnum))) { printf("open of \\ failed\n"); return false; } for (op=OP_MIN; op<=OP_MAX; op++) { printf("Scanning op=%d\n", op); for (level = 0; level <= 50; level++) { scan_trans2(cli, op, level, fnum, dnum, fname); } for (level = 0x100; level <= 0x130; level++) { scan_trans2(cli, op, level, fnum, dnum, fname); } for (level = 1000; level < 1050; level++) { scan_trans2(cli, op, level, fnum, dnum, fname); } } torture_close_connection(cli); printf("trans2 scan finished\n"); return True; }
/* basic testing of seek calls */ BOOL torture_raw_seek(struct torture_context *torture) { struct smbcli_state *cli; BOOL ret = True; TALLOC_CTX *mem_ctx; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_raw_seek"); if (!test_seek(cli, mem_ctx)) { ret = False; } torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
/* basic testing of write calls */ BOOL torture_raw_write(struct torture_context *torture) { struct smbcli_state *cli; BOOL ret = True; TALLOC_CTX *mem_ctx; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_raw_write"); ret &= test_write(cli, mem_ctx); ret &= test_writeunlock(cli, mem_ctx); ret &= test_writeclose(cli, mem_ctx); ret &= test_writex(cli, mem_ctx); torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
/* basic testing of read calls */ BOOL torture_raw_read(struct torture_context *torture) { struct smbcli_state *cli; BOOL ret = True; TALLOC_CTX *mem_ctx; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_raw_read"); ret &= test_read(cli, mem_ctx); ret &= test_readx(cli, mem_ctx); ret &= test_lockread(cli, mem_ctx); ret &= test_readbraw(cli, mem_ctx); ret &= test_read_for_execute(cli, mem_ctx); torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
BOOL torture_raw_qfileinfo_pipe(struct torture_context *torture) { TALLOC_CTX *mem_ctx; BOOL ret = True; int fnum; const char *fname = "\\lsass"; struct smbcli_state *cli; struct dcerpc_pipe *p; struct smbcli_tree *ipc_tree; NTSTATUS status; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_qfileinfo_pipe"); if (!(p = dcerpc_pipe_init(mem_ctx, cli->tree->session->transport->socket->event.ctx))) { return False; } status = dcerpc_pipe_open_smb(p, cli->tree, fname); if (!NT_STATUS_IS_OK(status)) { d_printf("dcerpc_pipe_open_smb failed: %s\n", nt_errstr(status)); talloc_free(p); return False; } ipc_tree = dcerpc_smb_tree(p->conn); fnum = dcerpc_smb_fnum(p->conn); ret = torture_raw_qfileinfo_internals(torture, mem_ctx, ipc_tree, fnum, fname, True /* is_ipc */); talloc_free(p); return ret; }
bool nb_reconnect(struct smbcli_state **cli, struct torture_context *tctx, int client) { children[client].connected = false; if (*cli != NULL) { talloc_free(*cli); } if (!torture_open_connection(cli, tctx, client)) { printf("nb_reconnect: failed to connect\n"); *cli = NULL; return false; } nb_setup(*cli, client); if (!nb_reopen_all_files()) { printf("nb_reconnect: failed to reopen files in client %d\n", client); return false; } return true; }
bool torture_nttrans_scan(int dummy) { static struct cli_state *cli; int op, level; const char *fname = "\\scanner.dat"; int fnum, dnum; printf("starting nttrans scan test\n"); if (!torture_open_connection(&cli, 0)) { return False; } fnum = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE); dnum = cli_open(cli, "\\", O_RDONLY, DENY_NONE); for (op=OP_MIN; op<=OP_MAX; op++) { printf("Scanning op=%d\n", op); for (level = 0; level <= 50; level++) { scan_nttrans(cli, op, level, fnum, dnum, fname); } for (level = 0x100; level <= 0x130; level++) { scan_nttrans(cli, op, level, fnum, dnum, fname); } for (level = 1000; level < 1050; level++) { scan_nttrans(cli, op, level, fnum, dnum, fname); } } torture_close_connection(cli); printf("nttrans scan finished\n"); return True; }
bool torture_samba3_badpath(struct torture_context *torture) { struct smbcli_state *cli_nt = NULL; struct smbcli_state *cli_dos = NULL; const char *fname = "test.txt"; const char *fname1 = "test1.txt"; const char *dirname = "testdir"; char *fpath; char *fpath1; int fnum; NTSTATUS status; bool ret = true; TALLOC_CTX *mem_ctx; bool nt_status_support; torture_assert(torture, mem_ctx = talloc_init("torture_samba3_badpath"), "talloc_init failed"); nt_status_support = lpcfg_nt_status_support(torture->lp_ctx); torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n"); torture_assert_goto(torture, torture_open_connection(&cli_nt, torture, 0), ret, fail, "Could not open NTSTATUS connection\n"); torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n"); torture_assert_goto(torture, torture_open_connection(&cli_dos, torture, 1), ret, fail, "Could not open DOS connection\n"); torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", nt_status_support ? "yes":"no"), ret, fail, "Could not set 'nt status support' back to where it was\n"); torture_assert(torture, torture_setup_dir(cli_nt, dirname), "creating test directory"); status = smbcli_chkpath(cli_nt->tree, dirname); CHECK_STATUS(torture, status, NT_STATUS_OK); status = smbcli_chkpath(cli_nt->tree, talloc_asprintf(mem_ctx, "%s\\bla", dirname)); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_NOT_FOUND); status = smbcli_chkpath(cli_dos->tree, talloc_asprintf(mem_ctx, "%s\\bla", dirname)); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, talloc_asprintf(mem_ctx, "%s\\bla\\blub", dirname)); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_NOT_FOUND); status = smbcli_chkpath(cli_dos->tree, talloc_asprintf(mem_ctx, "%s\\bla\\blub", dirname)); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); torture_assert_goto(torture, fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname), ret, fail, "Could not allocate fpath\n"); fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath, smbcli_errstr(cli_nt->tree)); goto fail; } smbcli_close(cli_nt->tree, fnum); if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) { goto fail; } fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath1, smbcli_errstr(cli_nt->tree)); goto fail; } smbcli_close(cli_nt->tree, fnum); /* * Do a whole bunch of error code checks on chkpath */ status = smbcli_chkpath(cli_nt->tree, fpath); CHECK_STATUS(torture, status, NT_STATUS_NOT_A_DIRECTORY); status = smbcli_chkpath(cli_dos->tree, fpath); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, ".."); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = smbcli_chkpath(cli_dos->tree, ".."); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = smbcli_chkpath(cli_nt->tree, "."); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "."); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "\t"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "\t"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "\t\\bla"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "\t\\bla"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "<"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "<"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "<\\bla"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "<\\bla"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); /* * .... And the same gang against getatr. Note that the DOS error codes * differ.... */ status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OK); status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OK); status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); /* Try the same set with openX. */ status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); /* Let's test EEXIST error code mapping. */ status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED) || !torture_setting_bool(torture, "samba3", false)) { /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */ CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); } status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported)) || !torture_setting_bool(torture, "samba3", false)) { /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */ CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); } status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); /* Try the rename test. */ { union smb_rename io; memset(&io, '\0', sizeof(io)); io.rename.in.pattern1 = fpath1; io.rename.in.pattern2 = fpath; /* Try with SMBmv rename. */ status = smb_raw_rename(cli_nt->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = smb_raw_rename(cli_dos->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename)); /* Try with NT rename. */ io.generic.level = RAW_RENAME_NTRENAME; io.ntrename.in.old_name = fpath1; io.ntrename.in.new_name = fpath; io.ntrename.in.attrib = 0; io.ntrename.in.cluster_size = 0; io.ntrename.in.flags = RENAME_FLAG_RENAME; status = smb_raw_rename(cli_nt->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = smb_raw_rename(cli_dos->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename)); } goto done; fail: ret = false; done: if (cli_nt != NULL) { smbcli_deltree(cli_nt->tree, dirname); torture_close_connection(cli_nt); } if (cli_dos != NULL) { torture_close_connection(cli_dos); } talloc_free(mem_ctx); return ret; }
bool run_cleanup4(int dummy) { struct cli_state *cli1, *cli2; const char *fname = "\\cleanup4"; uint16_t fnum1, fnum2; NTSTATUS status; printf("CLEANUP4: Checking that a conflicting share mode is cleaned " "up\n"); if (!torture_open_connection(&cli1, 0)) { return false; } if (!torture_open_connection(&cli2, 0)) { return false; } status = cli_ntcreate( cli1, fname, 0, FILE_GENERIC_READ|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL); if (!NT_STATUS_IS_OK(status)) { printf("creating file failed: %s\n", nt_errstr(status)); return false; } status = cli_ntcreate( cli2, fname, 0, FILE_GENERIC_READ|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2, NULL); if (!NT_STATUS_IS_OK(status)) { printf("opening file 1st time failed: %s\n", nt_errstr(status)); return false; } status = smbXcli_conn_samba_suicide(cli1->conn, 1); if (!NT_STATUS_IS_OK(status)) { printf("smbXcli_conn_samba_suicide failed: %s\n", nt_errstr(status)); return false; } /* * The next open will conflict with both opens above. The first open * above will be correctly cleaned up. A bug in smbd iterating over * the share mode array made it skip the share conflict check for the * second open. Trigger this bug. */ status = cli_ntcreate( cli2, fname, 0, FILE_GENERIC_WRITE|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { printf("opening file 2nd time returned: %s\n", nt_errstr(status)); return false; } return true; }
bool run_cleanup2(int dummy) { struct cli_state *cli1, *cli2, *cli3; const char *fname = "\\cleanup2"; uint16_t fnum1, fnum2, fnum3; NTSTATUS status; char buf; printf("CLEANUP2: Checking that a conflicting brlock is cleaned up\n"); if (!torture_open_connection(&cli1, 0)) { return false; } status = cli_ntcreate( cli1, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL); if (!NT_STATUS_IS_OK(status)) { printf("open of %s failed (%s)\n", fname, nt_errstr(status)); return false; } status = cli_lock32(cli1, fnum1, 0, 1, 0, WRITE_LOCK); if (!NT_STATUS_IS_OK(status)) { printf("lock failed (%s)\n", nt_errstr(status)); return false; } if (!torture_open_connection(&cli3, 1)) { return false; } status = cli_ntcreate( cli3, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum3, NULL); if (!NT_STATUS_IS_OK(status)) { printf("open of %s failed (%s)\n", fname, nt_errstr(status)); return false; } status = cli_lock32(cli3, fnum3, 1, 1, 0, WRITE_LOCK); if (!NT_STATUS_IS_OK(status)) { printf("lock failed (%s)\n", nt_errstr(status)); return false; } status = cli_lock32(cli1, fnum1, 2, 1, 0, WRITE_LOCK); if (!NT_STATUS_IS_OK(status)) { printf("lock failed (%s)\n", nt_errstr(status)); return false; } /* * Check the file is indeed locked */ if (!torture_open_connection(&cli2, 1)) { return false; } status = cli_ntcreate( cli2, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2, NULL); if (!NT_STATUS_IS_OK(status)) { printf("open of %s failed (%s)\n", fname, nt_errstr(status)); return false; } buf = 'x'; status = cli_smbwrite(cli2, fnum2, &buf, 0, 1, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { printf("write succeeded\n"); return false; } /* * Kill the lock holder */ status = smbXcli_conn_samba_suicide(cli1->conn, 1); if (!NT_STATUS_IS_OK(status)) { printf("smbXcli_conn_samba_suicide failed: %s\n", nt_errstr(status)); return false; } /* * Give the suicidal smbd a bit of time to really pass away */ smb_msleep(1000); status = cli_smbwrite(cli2, fnum2, &buf, 0, 1, NULL); if (!NT_STATUS_IS_OK(status)) { printf("write failed: %s\n", nt_errstr(status)); return false; } return true; }
bool torture_samba3_posixtimedlock(struct torture_context *tctx) { struct smbcli_state *cli; NTSTATUS status; bool ret = true; const char *dirname = "posixlock"; const char *fname = "locked"; const char *fpath; const char *localdir; const char *localname; int fnum = -1; int fd = -1; struct flock posix_lock; union smb_lock io; struct smb_lock_entry lock_entry; struct smbcli_request *req; struct lock_result_state lock_result; struct tevent_timer *te; if (!torture_open_connection(&cli, tctx, 0)) { ret = false; goto done; } smbcli_deltree(cli->tree, dirname); status = smbcli_mkdir(cli->tree, dirname); if (!NT_STATUS_IS_OK(status)) { torture_warning(tctx, "smbcli_mkdir failed: %s\n", nt_errstr(status)); ret = false; goto done; } if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) { torture_warning(tctx, "talloc failed\n"); ret = false; goto done; } fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { torture_warning(tctx, "Could not create file %s: %s\n", fpath, smbcli_errstr(cli->tree)); ret = false; goto done; } if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) { torture_warning(tctx, "Need 'localdir' setting\n"); ret = false; goto done; } if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname, fname))) { torture_warning(tctx, "talloc failed\n"); ret = false; goto done; } /* * Lock a byte range from posix */ fd = open(localname, O_RDWR); if (fd == -1) { torture_warning(tctx, "open(%s) failed: %s\n", localname, strerror(errno)); goto done; } posix_lock.l_type = F_WRLCK; posix_lock.l_whence = SEEK_SET; posix_lock.l_start = 0; posix_lock.l_len = 1; if (fcntl(fd, F_SETLK, &posix_lock) == -1) { torture_warning(tctx, "fcntl failed: %s\n", strerror(errno)); ret = false; goto done; } /* * Try a cifs brlock without timeout to see if posix locking = yes */ io.lockx.in.ulock_cnt = 0; io.lockx.in.lock_cnt = 1; lock_entry.count = 1; lock_entry.offset = 0; lock_entry.pid = cli->tree->session->pid; io.lockx.level = RAW_LOCK_LOCKX; io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; io.lockx.in.timeout = 0; io.lockx.in.locks = &lock_entry; io.lockx.in.file.fnum = fnum; status = smb_raw_lock(cli->tree, &io); ret = true; CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); if (!ret) { goto done; } /* * Now fire off a timed brlock, unlock the posix lock and see if the * timed lock gets through. */ io.lockx.in.timeout = 5000; req = smb_raw_lock_send(cli->tree, &io); if (req == NULL) { torture_warning(tctx, "smb_raw_lock_send failed\n"); ret = false; goto done; } lock_result.done = false; req->async.fn = receive_lock_result; req->async.private_data = &lock_result; te = tevent_add_timer(req->transport->socket->event.ctx, tctx, timeval_current_ofs(1, 0), close_locked_file, &fd); if (te == NULL) { torture_warning(tctx, "tevent_add_timer failed\n"); ret = false; goto done; } while ((fd != -1) || (!lock_result.done)) { if (tevent_loop_once(req->transport->socket->event.ctx) == -1) { torture_warning(tctx, "tevent_loop_once failed: %s\n", strerror(errno)); ret = false; goto done; } } CHECK_STATUS(lock_result.status, NT_STATUS_OK); done: if (fnum != -1) { smbcli_close(cli->tree, fnum); } if (fd != -1) { close(fd); } smbcli_deltree(cli->tree, dirname); return ret; }
bool torture_utable(int dummy) { struct cli_state *cli; fstring fname, alt_name; uint16_t fnum; smb_ucs2_t c2; int c, len, fd; int chars_allowed=0, alt_allowed=0; uint8 valid[0x10000]; printf("starting utable\n"); if (!torture_open_connection(&cli, 0)) { return False; } memset(valid, 0, sizeof(valid)); cli_mkdir(cli, "\\utable"); cli_unlink(cli, "\\utable\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); for (c=1; c < 0x10000; c++) { size_t size = 0; char *p; SSVAL(&c2, 0, c); fstrcpy(fname, "\\utable\\x"); p = fname+strlen(fname); if (!convert_string(CH_UTF16LE, CH_UNIX, &c2, 2, p, sizeof(fname)-strlen(fname),&size)) { d_printf("convert_string %s failed !\n", fname); continue; } len = size; p[len] = 0; fstrcat(fname,"_a_long_extension"); if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum))) { continue; } chars_allowed++; cli_qpathinfo_alt_name(cli, fname, alt_name); if (strncmp(alt_name, "X_A_L", 5) != 0) { alt_allowed++; valid[c] = 1; d_printf("fname=[%s] alt_name=[%s]\n", fname, alt_name); } cli_close(cli, fnum); cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); if (c % 100 == 0) { printf("%d (%d/%d)\r", c, chars_allowed, alt_allowed); } } printf("%d (%d/%d)\n", c, chars_allowed, alt_allowed); cli_rmdir(cli, "\\utable"); d_printf("%d chars allowed %d alt chars allowed\n", chars_allowed, alt_allowed); fd = open("valid.dat", O_WRONLY|O_CREAT|O_TRUNC, 0644); if (fd == -1) { d_printf("Failed to create valid.dat - %s", strerror(errno)); return False; } if (write(fd, valid, 0x10000) != 0x10000) { d_printf("Failed to create valid.dat - %s", strerror(errno)); close(fd); return false; } close(fd); d_printf("wrote valid.dat\n"); return True; }
/* basic testing of all RAW_QFS_* calls for each call we test that it succeeds, and where possible test for consistency between the calls. Some of the consistency tests assume that the target filesystem is quiescent, which is sometimes hard to achieve */ BOOL torture_raw_qfsinfo(struct torture_context *torture) { struct smbcli_state *cli; int i; BOOL ret = True; int count; union smb_fsinfo *s1, *s2; TALLOC_CTX *mem_ctx; if (!torture_open_connection(&cli, 0)) { return False; } mem_ctx = talloc_init("torture_qfsinfo"); /* scan all the levels, pulling the results */ for (i=0; levels[i].name; i++) { printf("Running level %s\n", levels[i].name); levels[i].fsinfo.generic.level = levels[i].level; levels[i].status = smb_raw_fsinfo(cli->tree, mem_ctx, &levels[i].fsinfo); } /* check for completely broken levels */ for (count=i=0; levels[i].name; i++) { uint32_t cap = cli->transport->negotiate.capabilities; /* see if this server claims to support this level */ if ((cap & levels[i].capability_mask) != levels[i].capability_mask) { continue; } if (!NT_STATUS_IS_OK(levels[i].status)) { printf("ERROR: level %s failed - %s\n", levels[i].name, nt_errstr(levels[i].status)); count++; } } if (count != 0) { ret = False; printf("%d levels failed\n", count); if (count > 13) { printf("too many level failures - giving up\n"); goto done; } } printf("check for correct aliases\n"); s1 = find("SIZE_INFO"); s2 = find("SIZE_INFORMATION"); if (s1 && s2) { VAL_EQUAL(size_info, total_alloc_units, size_info, total_alloc_units); VAL_APPROX_EQUAL(size_info, avail_alloc_units, size_info, avail_alloc_units); VAL_EQUAL(size_info, sectors_per_unit, size_info, sectors_per_unit); VAL_EQUAL(size_info, bytes_per_sector, size_info, bytes_per_sector); } s1 = find("DEVICE_INFO"); s2 = find("DEVICE_INFORMATION"); if (s1 && s2) { VAL_EQUAL(device_info, device_type, device_info, device_type); VAL_EQUAL(device_info, characteristics, device_info, characteristics); } s1 = find("VOLUME_INFO"); s2 = find("VOLUME_INFORMATION"); if (s1 && s2) { STRUCT_EQUAL(volume_info, create_time, volume_info, create_time); VAL_EQUAL (volume_info, serial_number, volume_info, serial_number); STR_EQUAL (volume_info, volume_name.s, volume_info, volume_name.s); printf("volume_info.volume_name = '%s'\n", s1->volume_info.out.volume_name.s); } s1 = find("ATTRIBUTE_INFO"); s2 = find("ATTRIBUTE_INFORMATION"); if (s1 && s2) { VAL_EQUAL(attribute_info, fs_attr, attribute_info, fs_attr); VAL_EQUAL(attribute_info, max_file_component_length, attribute_info, max_file_component_length); STR_EQUAL(attribute_info, fs_type.s, attribute_info, fs_type.s); printf("attribute_info.fs_type = '%s'\n", s1->attribute_info.out.fs_type.s); } printf("check for consistent disk sizes\n"); s1 = find("DSKATTR"); s2 = find("ALLOCATION"); if (s1 && s2) { double size1, size2; double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size; size1 = 1.0 * s1->dskattr.out.units_total * s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size / scale; size2 = 1.0 * s2->allocation.out.sectors_per_unit * s2->allocation.out.total_alloc_units * s2->allocation.out.bytes_per_sector / scale; if (abs(size1 - size2) > 1) { printf("Inconsistent total size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n", size1, size2); ret = False; } printf("total disk = %.0f MB\n", size1*scale/1.0e6); } printf("check consistent free disk space\n"); s1 = find("DSKATTR"); s2 = find("ALLOCATION"); if (s1 && s2) { double size1, size2; double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size; size1 = 1.0 * s1->dskattr.out.units_free * s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size / scale; size2 = 1.0 * s2->allocation.out.sectors_per_unit * s2->allocation.out.avail_alloc_units * s2->allocation.out.bytes_per_sector / scale; if (abs(size1 - size2) > 1) { printf("Inconsistent avail size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n", size1, size2); ret = False; } printf("free disk = %.0f MB\n", size1*scale/1.0e6); } printf("volume info consistency\n"); s1 = find("VOLUME"); s2 = find("VOLUME_INFO"); if (s1 && s2) { VAL_EQUAL(volume, serial_number, volume_info, serial_number); STR_EQUAL(volume, volume_name.s, volume_info, volume_name.s); } /* disk size consistency - notice that 'avail_alloc_units' maps to the caller available allocation units, not the total */ s1 = find("SIZE_INFO"); s2 = find("FULL_SIZE_INFORMATION"); if (s1 && s2) { VAL_EQUAL(size_info, total_alloc_units, full_size_information, total_alloc_units); VAL_APPROX_EQUAL(size_info, avail_alloc_units, full_size_information, call_avail_alloc_units); VAL_EQUAL(size_info, sectors_per_unit, full_size_information, sectors_per_unit); VAL_EQUAL(size_info, bytes_per_sector, full_size_information, bytes_per_sector); } printf("check for non-zero unknown fields\n"); s1 = find("QUOTA_INFORMATION"); if (s1) { VAL_UNKNOWN(quota_information, unknown[0]); VAL_UNKNOWN(quota_information, unknown[1]); VAL_UNKNOWN(quota_information, unknown[2]); } s1 = find("OBJECTID_INFORMATION"); if (s1) { VAL_UNKNOWN(objectid_information, unknown[0]); VAL_UNKNOWN(objectid_information, unknown[1]); VAL_UNKNOWN(objectid_information, unknown[2]); VAL_UNKNOWN(objectid_information, unknown[3]); VAL_UNKNOWN(objectid_information, unknown[4]); VAL_UNKNOWN(objectid_information, unknown[5]); } #define STR_CHECK(sname, stype, field, flags) do { \ s1 = find(sname); \ if (s1) { \ if (s1->stype.out.field.s && wire_bad_flags(&s1->stype.out.field, flags, cli)) { \ printf("(%d) incorrect string termination in %s/%s\n", \ __LINE__, #stype, #field); \ ret = False; \ } \ }} while (0) printf("check for correct termination\n"); STR_CHECK("VOLUME", volume, volume_name, 0); STR_CHECK("VOLUME_INFO", volume_info, volume_name, STR_UNICODE); STR_CHECK("VOLUME_INFORMATION", volume_info, volume_name, STR_UNICODE); STR_CHECK("ATTRIBUTE_INFO", attribute_info, fs_type, STR_UNICODE); STR_CHECK("ATTRIBUTE_INFORMATION", attribute_info, fs_type, STR_UNICODE); done: torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
bool run_posix_append(int dummy) { struct cli_state *cli; const char *fname = "append"; NTSTATUS status; uint16_t fnum; SMB_OFF_T size; uint8_t c = '\0'; bool ret = false; printf("Starting POSIX_APPEND\n"); if (!torture_open_connection(&cli, 0)) { return false; } status = torture_setup_unix_extensions(cli); if (!NT_STATUS_IS_OK(status)) { printf("torture_setup_unix_extensions failed: %s\n", nt_errstr(status)); goto fail; } status = cli_ntcreate( cli, fname, 0, GENERIC_WRITE_ACCESS|GENERIC_READ_ACCESS|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_POSIX_SEMANTICS, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE|FILE_DELETE_ON_CLOSE, 0, &fnum); if (!NT_STATUS_IS_OK(status)) { printf("cli_ntcreate failed: %s\n", nt_errstr(status)); goto fail; } /* * Write two bytes at offset 0. With bug 6898 we would end up * with a file of 2 byte length. */ status = cli_writeall(cli, fnum, 0, &c, 0, sizeof(c), NULL); if (!NT_STATUS_IS_OK(status)) { printf("cli_write failed: %s\n", nt_errstr(status)); goto fail; } status = cli_writeall(cli, fnum, 0, &c, 0, sizeof(c), NULL); if (!NT_STATUS_IS_OK(status)) { printf("cli_write failed: %s\n", nt_errstr(status)); goto fail; } status = cli_getattrE(cli, fnum, NULL, &size, NULL, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { printf("cli_getatrE failed: %s\n", nt_errstr(status)); goto fail; } if (size != sizeof(c)) { printf("BUG: Writing with O_APPEND!!\n"); goto fail; } ret = true; fail: torture_close_connection(cli); return ret; }
bool torture_samba3_closeerr(struct torture_context *tctx) { struct smbcli_state *cli = NULL; bool result = false; NTSTATUS status; const char *dname = "closeerr.dir"; const char *fname = "closeerr.dir\\closerr.txt"; int fnum; if (!torture_open_connection(&cli, tctx, 0)) { goto fail; } smbcli_deltree(cli->tree, dname); torture_assert_ntstatus_ok( tctx, smbcli_mkdir(cli->tree, dname), talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n", smbcli_errstr(cli->tree))); fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "smbcli_open failed: %s\n", smbcli_errstr(cli->tree))); smbcli_close(cli->tree, fnum); fnum = smbcli_nt_create_full(cli->tree, fname, 0, SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "smbcli_open failed: %s\n", smbcli_errstr(cli->tree))); status = smbcli_nt_delete_on_close(cli->tree, fnum, true); torture_assert_ntstatus_ok(tctx, status, "setting delete_on_close on file failed !"); status = smbcli_chmod(cli->tree, dname, 0); torture_assert_ntstatus_ok(tctx, status, "smbcli_chmod on file failed !"); status = smbcli_close(cli->tree, fnum); smbcli_chmod(cli->tree, dname, UNIX_R_USR|UNIX_W_USR|UNIX_X_USR); smbcli_deltree(cli->tree, dname); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_ACCESS_DENIED, "smbcli_close"); result = true; fail: if (cli) { torture_close_connection(cli); } return result; }
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; }
bool torture_casetable(int dummy) { static struct cli_state *cli; char *fname; uint16_t fnum; int c, i; #define MAX_EQUIVALENCE 8 smb_ucs2_t equiv[0x10000][MAX_EQUIVALENCE]; printf("starting casetable\n"); if (!torture_open_connection(&cli, 0)) { return False; } memset(equiv, 0, sizeof(equiv)); cli_unlink(cli, "\\utable\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); cli_rmdir(cli, "\\utable"); if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\utable"))) { printf("Failed to create utable directory!\n"); return False; } for (c=1; c < 0x10000; c++) { SMB_OFF_T size; if (c == '.' || c == '\\') continue; printf("%04x (%c)\n", c, isprint(c)?c:'.'); fname = form_name(c); if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum))) { printf("Failed to create file with char %04x\n", c); continue; } size = 0; if (!NT_STATUS_IS_OK(cli_qfileinfo_basic( cli, fnum, NULL, &size, NULL, NULL, NULL, NULL, NULL))) { continue; } if (size > 0) { /* found a character equivalence! */ int c2[MAX_EQUIVALENCE]; if (size/sizeof(int) >= MAX_EQUIVALENCE) { printf("too many chars match?? size=%ld c=0x%04x\n", (unsigned long)size, c); cli_close(cli, fnum); return False; } cli_read(cli, fnum, (char *)c2, 0, size); printf("%04x: ", c); equiv[c][0] = c; for (i=0; i<size/sizeof(int); i++) { printf("%04x ", c2[i]); equiv[c][i+1] = c2[i]; } printf("\n"); fflush(stdout); } cli_writeall(cli, fnum, 0, (uint8_t *)&c, size, sizeof(c), NULL); cli_close(cli, fnum); } cli_unlink(cli, "\\utable\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); cli_rmdir(cli, "\\utable"); return True; }
bool torture_samba3_rootdirfid(struct torture_context *tctx) { struct smbcli_state *cli; NTSTATUS status; uint16_t dnum; union smb_open io; const char *fname = "testfile"; bool ret = false; 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_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 = "\\"; status = smb_raw_open(cli->tree, tctx, &io); if (!NT_STATUS_IS_OK(status)) { d_printf("smb_open on the directory failed: %s\n", nt_errstr(status)); ret = false; goto done; } 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; status = smb_raw_open(cli->tree, tctx, &io); if (!NT_STATUS_IS_OK(status)) { d_printf("smb_open on the file %s failed: %s\n", fname, nt_errstr(status)); ret = false; goto done; } smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); smbcli_close(cli->tree, dnum); smbcli_unlink(cli->tree, fname); ret = true; done: return ret; }
/* ping pong */ bool torture_ping_pong(struct torture_context *torture) { const char *fn; int num_locks; TALLOC_CTX *mem_ctx = talloc_new(torture); static bool do_reads; static bool do_writes; int lock_timeout; int fd; struct smbcli_state *cli; int i; uint8_t incr=0, last_incr=0; uint8_t *val; int count, loops; struct timeval start; fn = torture_setting_string(torture, "filename", NULL); if (fn == NULL) { DEBUG(0,("You must specify the filename using --option=torture:filename=...\n")); return false; } num_locks = torture_setting_int(torture, "num_locks", -1); if (num_locks == -1) { DEBUG(0,("You must specify num_locks using --option=torture:num_locks=...\n")); return false; } do_reads = torture_setting_bool(torture, "read", false); do_writes = torture_setting_bool(torture, "write", false); lock_timeout = torture_setting_int(torture, "lock_timeout", 100000); if (!torture_open_connection(&cli, torture, 0)) { DEBUG(0,("Could not open connection\n")); return false; } fd = smbcli_open(cli->tree, fn, O_RDWR|O_CREAT, DENY_NONE); if (fd == -1) { printf("Failed to open %s\n", fn); exit(1); } write_byte(cli, fd, 0, num_locks); lock_byte(cli, fd, 0, lock_timeout); start = timeval_current(); val = talloc_zero_array(mem_ctx, uint8_t, num_locks); i = 0; count = 0; loops = 0; while (1) { lock_byte(cli, fd, (i+1)%num_locks, lock_timeout); if (do_reads) { uint8_t c; read_byte(cli, fd, &c, i); incr = c-val[i]; val[i] = c; } if (do_writes) { uint8_t c = val[i] + 1; write_byte(cli, fd, c, i); } unlock_byte(cli, fd, i); i = (i+1)%num_locks; count++; if (loops>num_locks && incr!=last_incr) { last_incr = incr; printf("data increment = %u\n", incr); fflush(stdout); } if (timeval_elapsed(&start) > 1.0) { printf("%8u locks/sec\r", (unsigned)(2*count/timeval_elapsed(&start))); fflush(stdout); start = timeval_current(); count=0; } loops++; } }