Skip to content

Commit

Permalink
s3: smbtorture: Add new SMB2-DIR-FSYNC test to show behavior of FSYNC…
Browse files Browse the repository at this point in the history
… on directories.

Tests against a directory handle on the root of a share,
and a directory handle on a sub-directory in a share.

Check SEC_DIR_ADD_FILE and SEC_DIR_ADD_SUBDIR separately,
either allows flush to succeed.

Passes against Windows.

Regression test for:

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13428

Signed-off-by: Jeremy Allison <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>

Autobuild-User(master): Jeremy Allison <[email protected]>
Autobuild-Date(master): Fri May 18 02:38:50 CEST 2018 on sn-devel-144
  • Loading branch information
jrasamba committed May 18, 2018
1 parent 42aadf4 commit d42f467
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 1 deletion.
1 change: 1 addition & 0 deletions selftest/knownfail
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
.*driver.add_driver_timestamps # we only can store dates, not timestamps
^samba3.smbtorture_s3.crypt_server\(nt4_dc\).SMB2-SESSION-REAUTH # expected to give ACCESS_DENIED SMB2.1 doesn't have encryption
^samba3.smbtorture_s3.crypt_server\(nt4_dc\).SMB2-SESSION-RECONNECT # expected to give CONNECTION_DISCONNECTED, we need to fix the test
^samba3.smbtorture_s3.*ad_dc_ntvfs.*SMB2-DIR-FSYNC.*
^samba3.smb2.session enc.reconnect # expected to give CONNECTION_DISCONNECTED, we need to fix the test
^samba3.raw.session enc # expected to give ACCESS_DENIED as SMB1 encryption isn't used
^samba3.smbtorture_s3.crypt_server # expected to give ACCESS_DENIED as SMB1 encryption isn't used
Expand Down
2 changes: 1 addition & 1 deletion source3/selftest/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def plansmbtorture4testsuite(name, env, options, description=''):
"UID-REGRESSION-TEST", "SHORTNAME-TEST",
"CASE-INSENSITIVE-CREATE", "SMB2-BASIC", "NTTRANS-FSCTL", "SMB2-NEGPROT",
"SMB2-SESSION-REAUTH", "SMB2-SESSION-RECONNECT", "SMB2-FTRUNCATE",
"SMB2-ANONYMOUS",
"SMB2-ANONYMOUS", "SMB2-DIR-FSYNC",
"CLEANUP1",
"CLEANUP2",
"CLEANUP4",
Expand Down
1 change: 1 addition & 0 deletions source3/torture/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ bool run_smb2_tcon_dependence(int dummy);
bool run_smb2_multi_channel(int dummy);
bool run_smb2_session_reauth(int dummy);
bool run_smb2_ftruncate(int dummy);
bool run_smb2_dir_fsync(int dummy);
bool run_chain3(int dummy);
bool run_local_conv_auth_info(int dummy);
bool run_local_sprintf_append(int dummy);
Expand Down
270 changes: 270 additions & 0 deletions source3/torture/test_smb2.c
Original file line number Diff line number Diff line change
Expand Up @@ -2065,3 +2065,273 @@ bool run_smb2_ftruncate(int dummy)
}
return correct;
}

/* Ensure SMB2 flush on directories behaves correctly. */

static bool test_dir_fsync(struct cli_state *cli, const char *path)
{
NTSTATUS status;
uint64_t fid_persistent, fid_volatile;
uint8_t *dir_data = NULL;
uint32_t dir_data_length = 0;

/* Open directory - no write abilities. */
status = smb2cli_create(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, path,
SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
SEC_STD_SYNCHRONIZE|
SEC_DIR_LIST|
SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
0, /* file_attributes, */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
FILE_OPEN, /* create_disposition, */
FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, /* create_options, */
NULL, /* smb2_create_blobs *blobs */
&fid_persistent,
&fid_volatile,
NULL, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_create '%s' (readonly) returned %s\n",
path,
nt_errstr(status));
return false;
}

status = smb2cli_query_directory(
cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
talloc_tos(), &dir_data, &dir_data_length);

if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_query_directory returned %s\n",
nt_errstr(status));
return false;
}

/* Open directory no write access. Flush should fail. */

status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, fid_persistent, fid_volatile);
if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
printf("smb2cli_flush on a read-only directory returned %s\n",
nt_errstr(status));
return false;
}

status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, 0, fid_persistent, fid_volatile);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_close returned %s\n", nt_errstr(status));
return false;
}

/* Open directory write-attributes only. Flush should still fail. */

status = smb2cli_create(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, path,
SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
SEC_STD_SYNCHRONIZE|
SEC_DIR_LIST|
SEC_DIR_WRITE_ATTRIBUTE|
SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
0, /* file_attributes, */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
FILE_OPEN, /* create_disposition, */
FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, /* create_options, */
NULL, /* smb2_create_blobs *blobs */
&fid_persistent,
&fid_volatile,
NULL, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_create '%s' (write attr) returned %s\n",
path,
nt_errstr(status));
return false;
}

status = smb2cli_query_directory(
cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
talloc_tos(), &dir_data, &dir_data_length);

if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
return false;
}

status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, fid_persistent, fid_volatile);
if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
printf("smb2cli_flush on a write-attributes directory "
"returned %s\n",
nt_errstr(status));
return false;
}

status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, 0, fid_persistent, fid_volatile);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_close returned %s\n", nt_errstr(status));
return false;
}

/* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */

status = smb2cli_create(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, path,
SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
SEC_STD_SYNCHRONIZE|
SEC_DIR_LIST|
SEC_DIR_ADD_FILE, /* desired_access, */
0, /* file_attributes, */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
FILE_OPEN, /* create_disposition, */
FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, /* create_options, */
NULL, /* smb2_create_blobs *blobs */
&fid_persistent,
&fid_volatile,
NULL, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_create '%s' (write FILE access) returned %s\n",
path,
nt_errstr(status));
return false;
}

status = smb2cli_query_directory(
cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
talloc_tos(), &dir_data, &dir_data_length);

if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
return false;
}

status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, fid_persistent, fid_volatile);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_flush on a directory returned %s\n",
nt_errstr(status));
return false;
}

status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, 0, fid_persistent, fid_volatile);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_close returned %s\n", nt_errstr(status));
return false;
}

/* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */

status = smb2cli_create(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, path,
SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
SEC_STD_SYNCHRONIZE|
SEC_DIR_LIST|
SEC_DIR_ADD_SUBDIR, /* desired_access, */
0, /* file_attributes, */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
FILE_OPEN, /* create_disposition, */
FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, /* create_options, */
NULL, /* smb2_create_blobs *blobs */
&fid_persistent,
&fid_volatile,
NULL, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_create '%s' (write DIR access) returned %s\n",
path,
nt_errstr(status));
return false;
}

status = smb2cli_query_directory(
cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
talloc_tos(), &dir_data, &dir_data_length);

if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
return false;
}

status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, fid_persistent, fid_volatile);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_flush on a directory returned %s\n",
nt_errstr(status));
return false;
}

status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
cli->smb2.tcon, 0, fid_persistent, fid_volatile);
if (!NT_STATUS_IS_OK(status)) {
printf("smb2cli_close returned %s\n", nt_errstr(status));
return false;
}


return true;
}

bool run_smb2_dir_fsync(int dummy)
{
struct cli_state *cli = NULL;
NTSTATUS status;
bool bret = false;
const char *dname = "fsync_test_dir";

printf("Starting SMB2-DIR-FSYNC\n");

if (!torture_init_connection(&cli)) {
return false;
}

status = smbXcli_negprot(cli->conn, cli->timeout,
PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
if (!NT_STATUS_IS_OK(status)) {
printf("smbXcli_negprot returned %s\n", nt_errstr(status));
return false;
}

status = cli_session_setup_creds(cli, torture_creds);
if (!NT_STATUS_IS_OK(status)) {
printf("cli_session_setup returned %s\n", nt_errstr(status));
return false;
}

status = cli_tree_connect(cli, share, "?????", NULL);
if (!NT_STATUS_IS_OK(status)) {
printf("cli_tree_connect returned %s\n", nt_errstr(status));
return false;
}

(void)cli_rmdir(cli, dname);
status = cli_mkdir(cli, dname);
if (!NT_STATUS_IS_OK(status)) {
printf("cli_mkdir(%s) returned %s\n",
dname,
nt_errstr(status));
return false;
}

/* Test on a subdirectory. */
bret = test_dir_fsync(cli, dname);
if (bret == false) {
(void)cli_rmdir(cli, dname);
return false;
}
(void)cli_rmdir(cli, dname);

/* Test on the root handle of a share. */
bret = test_dir_fsync(cli, "");
if (bret == false) {
return false;
}
return true;
}
1 change: 1 addition & 0 deletions source3/torture/torture.c
Original file line number Diff line number Diff line change
Expand Up @@ -11595,6 +11595,7 @@ static struct {
{ "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
{ "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
{ "SMB2-FTRUNCATE", run_smb2_ftruncate },
{ "SMB2-DIR-FSYNC", run_smb2_dir_fsync },
{ "CLEANUP1", run_cleanup1 },
{ "CLEANUP2", run_cleanup2 },
{ "CLEANUP3", run_cleanup3 },
Expand Down

0 comments on commit d42f467

Please sign in to comment.