From: Jeremy Allison Date: Wed, 7 Sep 2022 00:25:18 +0000 (-0700) Subject: s3: smbtorture3: Add an SMB1 operations torture tester. X-Git-Tag: talloc-2.4.0~1055 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ddc88e5c5ab4e62869816e38ea619e9f48fd46f4;p=thirdparty%2Fsamba.git s3: smbtorture3: Add an SMB1 operations torture tester. Only tests SMB1unlink for now, but I will add other operations later. smbtorture3 test is: SMB1-DFS-OPERATIONS. Passes fully against Windows. Adds knownfail for smbd. Signed-off-by: Jeremy Allison Reviewed-by: Noel Power --- diff --git a/selftest/knownfail.d/dfs_paths b/selftest/knownfail.d/dfs_paths index 330c17d02a0..64ddfc9160a 100644 --- a/selftest/knownfail.d/dfs_paths +++ b/selftest/knownfail.d/dfs_paths @@ -2,3 +2,4 @@ ^samba3.smbtorture_s3.smb2.SMB2-NON-DFS-SHARE.smbtorture\(fileserver\) ^samba3.smbtorture_s3.smb1.SMB1-DFS-PATHS.smbtorture\(fileserver\) ^samba3.smbtorture_s3.smb1.SMB1-DFS-SEARCH-PATHS.smbtorture\(fileserver\) +^samba3.smbtorture_s3.smb1.SMB1-DFS-OPERATIONS.smbtorture\(fileserver\) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index b11fedd6c4f..68959ba0b90 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -296,6 +296,22 @@ plantestsuite("samba3.smbtorture_s3.smb1.SMB1-DFS-SEARCH-PATHS", smbtorture3, "-mNT1"]) +# +# SMB1-DFS-OPERATIONS needs to run against a special share msdfs-pathname-share +# This is an empty DFS share with no links, used merely to test +# incoming DFS pathnames and how they map to local paths. +# +plantestsuite("samba3.smbtorture_s3.smb1.SMB1-DFS-OPERATIONS", + "fileserver", + [os.path.join(samba3srcdir, + "script/tests/test_smbtorture_s3.sh"), + 'SMB1-DFS-OPERATIONS', + '//$SERVER_IP/msdfs-pathname-share', + '$USERNAME', + '$PASSWORD', + smbtorture3, + "-mNT1"]) + # # SMB2-STREAM-ACL needs to run against a special share - vfs_wo_fruit # diff --git a/source3/torture/proto.h b/source3/torture/proto.h index d5e404eaefa..7093e8a7665 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -124,6 +124,7 @@ bool run_smb2_dfs_paths(int dummy); bool run_smb2_non_dfs_share(int dummy); bool run_smb1_dfs_paths(int dummy); bool run_smb1_dfs_search_paths(int dummy); +bool run_smb1_dfs_operations(int dummy); bool run_list_dir_async_test(int dummy); bool run_delete_on_close_non_empty(int dummy); bool run_delete_on_close_nonwrite_delete_yes_test(int dummy); diff --git a/source3/torture/test_smb1_dfs.c b/source3/torture/test_smb1_dfs.c index 1acea318e37..211be4e1aba 100644 --- a/source3/torture/test_smb1_dfs.c +++ b/source3/torture/test_smb1_dfs.c @@ -2361,3 +2361,202 @@ bool run_smb1_dfs_search_paths(int dummy) (void)smb1_dfs_delete(cli, "BAD\\BAD\\file"); return retval; } + +static bool smb1_create_testfile(struct cli_state *cli, + const char *path) +{ + NTSTATUS status; + uint16_t fnum = (uint16_t)-1; + + /* Create a test file. */ + status = smb1cli_ntcreatex(cli->conn, + cli->timeout, + cli->smb1.pid, + cli->smb1.tcon, + cli->smb1.session, + path, + OPLOCK_NONE, /* CreatFlags */ + 0, /* RootDirectoryFid */ + SEC_STD_SYNCHRONIZE| + SEC_STD_DELETE | + SEC_FILE_READ_DATA| + SEC_FILE_READ_ATTRIBUTE, /* DesiredAccess */ + 0, /* AllocationSize */ + FILE_ATTRIBUTE_NORMAL, /* FileAttributes */ + FILE_SHARE_READ| + FILE_SHARE_WRITE| + FILE_SHARE_DELETE, /* ShareAccess */ + FILE_CREATE, /* CreateDisposition */ + 0, /* CreateOptions */ + 2, /* ImpersonationLevel */ + 0, /* SecurityFlags */ + &fnum); + if (!NT_STATUS_IS_OK(status)) { + printf("%s:%d smb1cli_ntcreatex on %s returned %s\n", + __FILE__, + __LINE__, + path, + nt_errstr(status)); + return false; + } + + /* Close "file" handle. */ + (void)smb1cli_close(cli->conn, + cli->timeout, + cli->smb1.pid, + cli->smb1.tcon, + cli->smb1.session, + fnum, + 0); /* last_modified */ + return true; +} + +static NTSTATUS smb1_unlink(struct cli_state *cli, + const char *path) +{ + uint16_t vwv[1]; + uint8_t *bytes = NULL; + + PUSH_LE_U16(vwv, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); + bytes = talloc_array(talloc_tos(), uint8_t, 1); + if (bytes == NULL) { + return NT_STATUS_NO_MEMORY; + } + bytes[0] = 4; + bytes = smb_bytes_push_str(bytes, + smbXcli_conn_use_unicode(cli->conn), + path, + strlen(path)+1, + NULL); + if (bytes == NULL) { + return NT_STATUS_NO_MEMORY; + } + + return cli_smb(talloc_tos(), + cli, + SMBunlink, /* command. */ + 0, /* additional_flags. */ + 1, /* wct. */ + vwv, /* vwv. */ + talloc_get_size(bytes), /* num_bytes. */ + bytes, /* bytes. */ + NULL, /* result parent. */ + 0, /* min_wct. */ + NULL, /* return wcount. */ + NULL, /* return wvw. */ + NULL, /* return byte count. */ + NULL); /* return bytes. */ +} + +static bool test_smb1_unlink(struct cli_state *cli) +{ + NTSTATUS status; + bool retval = false; + bool ok = false; + + /* Start clean. */ + (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\file"); + + /* Create a test file. */ + ok = smb1_create_testfile(cli, "\\BAD\\BAD\\file"); + if (!ok) { + printf("%s:%d failed to create test file %s\n", + __FILE__, + __LINE__, + "\\BAD\\BAD\\file"); + goto err; + } + + status = smb1_unlink(cli, "file"); + if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + printf("%s:%d SMB1unlink of %s should get " + "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n", + __FILE__, + __LINE__, + "file", + nt_errstr(status)); + goto err; + } + status = smb1_unlink(cli, "\\BAD\\file"); + if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + printf("%s:%d SMB1unlink of %s should get " + "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n", + __FILE__, + __LINE__, + "\\BAD\\file", + nt_errstr(status)); + goto err; + } + status = smb1_unlink(cli, "\\BAD\\BAD\\file"); + if (!NT_STATUS_IS_OK(status)) { + printf("%s:%d SMB1unlink on %s returned %s\n", + __FILE__, + __LINE__, + "\\BAD\\BAD\\file", + nt_errstr(status)); + goto err; + } + + retval = true; + + err: + + (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\file"); + return retval; +} + +/* + * "Raw" test of different SMB1 operations to a DFS share. + * We must (mostly) use the lower level smb1cli_XXXX() interfaces, + * not the cli_XXX() ones here as the ultimate goal is to fix our + * cli_XXX() interfaces to work transparently over DFS. + * + * So here, we're testing the server code, not the client code. + * + * Passes cleanly against Windows. + */ + +bool run_smb1_dfs_operations(int dummy) +{ + struct cli_state *cli = NULL; + bool dfs_supported = false; + bool retval = false; + bool ok = false; + + printf("Starting SMB1-DFS-OPS\n"); + + if (!torture_init_connection(&cli)) { + return false; + } + + if (!torture_open_connection(&cli, 0)) { + return false; + } + + /* Ensure this is a DFS share. */ + dfs_supported = smbXcli_conn_dfs_supported(cli->conn); + if (!dfs_supported) { + printf("Server %s does not support DFS\n", + smbXcli_conn_remote_name(cli->conn)); + return false; + } + dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb1.tcon); + if (!dfs_supported) { + printf("Share %s does not support DFS\n", + cli->share); + return false; + } + + ok = test_smb1_unlink(cli); + if (!ok) { + goto err; + } + + retval = true; + + err: + + /* Delete anything we made. */ + (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\file"); + return retval; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 75d0248d773..2bd15fcec00 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -15375,6 +15375,10 @@ static struct { .name = "SMB1-DFS-SEARCH-PATHS", .fn = run_smb1_dfs_search_paths, }, + { + .name = "SMB1-DFS-OPERATIONS", + .fn = run_smb1_dfs_operations, + }, { .name = "CLEANUP1", .fn = run_cleanup1,