From 5323fe99c30bad099645711feac5f2a8979a1ee1 Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Sun, 10 Jan 2010 16:06:57 -0800 Subject: s4/torture: Parameterize output in LOCK tests based off server support Two new torture parameters: * smbexit_pdu_support: if the Server supports the Exit command * range_not_locked_on_file_close: whether the server returns the NT_STATUS_RANGE_NOT_LOCKED error when a file is closed which has a pending lock request. Windows returns this error, though per the spec, this error should only be returned to an unlock request. --- source4/torture/raw/lock.c | 120 ++++++++++++++++++++++++++----------------- source4/torture/smbtorture.c | 3 ++ source4/torture/smbtorture.h | 14 +++++ 3 files changed, 90 insertions(+), 47 deletions(-) diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c index 7eb461048b..6c86a6f615 100644 --- a/source4/torture/raw/lock.c +++ b/source4/torture/raw/lock.c @@ -80,10 +80,14 @@ #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \ (torture_setting_bool(_tctx, "invalid_lock_range_support", true)) +#define TARGET_SUPPORTS_SMBEXIT(_tctx) \ + (torture_setting_bool(_tctx, "smbexit_pdu_support", true)) #define TARGET_SUPPORTS_SMBLOCK(_tctx) \ (torture_setting_bool(_tctx, "smblock_pdu_support", true)) #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \ (torture_setting_bool(_tctx, "openx_deny_dos_support", true)) +#define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \ + (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true)) /* test SMBlock and SMBunlock ops */ @@ -786,7 +790,10 @@ static bool test_async(struct torture_context *tctx, CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_request_simple_recv(req); - CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + else + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx, "lock cancel by close was not immediate (%s)\n", __location__)); @@ -816,46 +823,57 @@ static bool test_async(struct torture_context *tctx, tree->tid = tcon.tconx.out.tid; torture_comment(tctx, "testing cancel by exit\n"); - fname = BASEDIR "\\test_exit.txt"; - fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE); - torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx, - "Failed to reopen %s - %s\n", - fname, smbcli_errstr(tree))); - - io.lockx.level = RAW_LOCK_LOCKX; - io.lockx.in.file.fnum = fnum; - io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; - io.lockx.in.timeout = 0; - io.lockx.in.ulock_cnt = 0; - io.lockx.in.lock_cnt = 1; - lock[0].pid = session->pid; - lock[0].offset = 100; - lock[0].count = 10; - io.lockx.in.locks = &lock[0]; - status = smb_raw_lock(tree, &io); - CHECK_STATUS(status, NT_STATUS_OK); - - io.lockx.in.ulock_cnt = 0; - io.lockx.in.lock_cnt = 1; - io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; - io.lockx.in.timeout = 0; - status = smb_raw_lock(tree, &io); - CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + if (TARGET_SUPPORTS_SMBEXIT(tctx)) { + fname = BASEDIR "\\test_exit.txt"; + fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE); + torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx, + "Failed to reopen %s - %s\n", + fname, smbcli_errstr(tree))); + + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); - io.lockx.in.timeout = 10000; - t = time(NULL); - req = smb_raw_lock_send(tree, &io); - torture_assert(tctx,(req != NULL), talloc_asprintf(tctx, - "Failed to setup timed lock (%s)\n", __location__)); + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + io.lockx.in.timeout = 10000; + t = time(NULL); + req = smb_raw_lock_send(tree, &io); + torture_assert(tctx,(req != NULL), talloc_asprintf(tctx, + "Failed to setup timed lock (%s)\n", + __location__)); + + status = smb_raw_exit(session); + CHECK_STATUS(status, NT_STATUS_OK); - status = smb_raw_exit(session); - CHECK_STATUS(status, NT_STATUS_OK); + status = smbcli_request_simple_recv(req); + if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + else + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); - status = smbcli_request_simple_recv(req); - CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); - - torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx, - "lock cancel by exit was not immediate (%s)\n", __location__)); + torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx, + "lock cancel by exit was not immediate (%s)\n", + __location__)); + } + else { + torture_comment(tctx, + " skipping test, SMBExit not supported\n"); + } torture_comment(tctx, "testing cancel by ulogoff\n"); fname = BASEDIR "\\test_ulogoff.txt"; @@ -894,15 +912,20 @@ static bool test_async(struct torture_context *tctx, CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_request_simple_recv(req); - if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) { - torture_result(tctx, TORTURE_FAIL, - "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n", - nt_errstr(status)); - smb_tree_disconnect(tree); - smb_raw_exit(session); - goto done; + if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) { + if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) { + torture_result(tctx, TORTURE_FAIL, + "lock not canceled by ulogoff - %s " + "(ignored because of vfs_vifs fails it)\n", + nt_errstr(status)); + smb_tree_disconnect(tree); + smb_raw_exit(session); + goto done; + } + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + } else { + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); } - CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx, "lock cancel by ulogoff was not immediate (%s)\n", __location__)); @@ -942,7 +965,10 @@ static bool test_async(struct torture_context *tctx, CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_request_simple_recv(req); - CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + else + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx, "lock cancel by tdis was not immediate (%s)\n", __location__)); diff --git a/source4/torture/smbtorture.c b/source4/torture/smbtorture.c index 8e0a25b032..53e860a144 100644 --- a/source4/torture/smbtorture.c +++ b/source4/torture/smbtorture.c @@ -550,8 +550,11 @@ int main(int argc,char *argv[]) lp_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true"); lp_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support", "false"); + lp_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false"); lp_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false"); lp_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false"); + lp_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support", + "false"); lp_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support", "false"); lp_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none", diff --git a/source4/torture/smbtorture.h b/source4/torture/smbtorture.h index 38969f1bcc..5b12f4e3f5 100644 --- a/source4/torture/smbtorture.h +++ b/source4/torture/smbtorture.h @@ -74,6 +74,15 @@ bool torture_register_suite(struct torture_suite *suite); * This parameter specifies whether the server supports the DENY_DOS open mode * of the SMBOpenX PDU. */ +/* torture:range_not_locked_on_file_close + * + * When a byte range lock is pending, and the file which is being locked is + * closed, Windows servers return the error NT_STATUS_RANGE_NOT_LOCKED. This + * is strange, as this error is meant to be returned only for unlock requests. + * When true, torture will expect the Windows behavior, otherwise it will + * expect the more logical NT_STATUS_LOCK_NOT_GRANTED. + */ + /* torture:sacl_support * * This parameter specifies whether the server supports the setting and @@ -81,6 +90,10 @@ bool torture_register_suite(struct torture_suite *suite); * supports the use of the SEC_FLAG_SYSTEM_SECURITY bit in the open access * mask.*/ +/* torture:smbexit_pdu_support + * + * This parameter specifies whether the server supports the SMBExit (0x11) PDU. */ + /* torture:smblock_pdu_support * * This parameter specifies whether the server supports the SMBLock (0x0C) PDU. */ @@ -119,4 +132,5 @@ bool torture_register_suite(struct torture_suite *suite); * denied. When true, torture will expect NT_STATUS_OBJECT_NAME_NOT_FOUND * rather than NT_STATUS_ACCESS_DENIED when trying to open one of these files. */ + #endif /* __SMBTORTURE_H__ */ -- cgit