From e7fd9e78cff7fc2c93043a052121b99923a4a09b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Feb 2019 17:52:34 -0800 Subject: [PATCH 1/5] s3: smbtorture3: Add POSIX-MKDIR test for posix_mkdir case sensitive bug. Test does: mkdir POSIX_foo mkdir POSIX_Foo mkdir POSIX_foo/Foo mkdir POSIX_foo/foo mkdir POSIX_Foo/Foo mkdir POSIX_Foo/foo Which should pass a SMB1 POSIX extensions server as posix mkdir should always be case sensitive no matter what the share is set to. Mark as knownfail for now. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit f0decb31fff24ceb57d23bebbfb87aa0e5103947) --- selftest/knownfail | 1 + selftest/skip | 1 + source3/selftest/tests.py | 2 +- source3/torture/torture.c | 100 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 1 deletion(-) diff --git a/selftest/knownfail b/selftest/knownfail index baf3d57a31a..951fbdd758e 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -9,6 +9,7 @@ ^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.smbtorture_s3.*.POSIX-MKDIR ^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 diff --git a/selftest/skip b/selftest/skip index dd60ab5a1fb..4d6648f3369 100644 --- a/selftest/skip +++ b/selftest/skip @@ -48,6 +48,7 @@ ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-SYMLINK-EA # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-OFD-LOCK # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-STREAM-DELETE # Fails against the s4 ntvfs server +^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-MKDIR # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).WINDOWS-BAD-SYMLINK # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).RENAME-ACCESS # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).OWNER-RIGHTS # Don't test against the s4 ntvfs server anymore diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 96524d1748f..e3187ca80c3 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -117,7 +117,7 @@ for t in tests: plantestsuite("samba3.smbtorture_s3.vfs_aio_fork(simpleserver).%s" % t, "simpleserver", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/vfs_aio_fork', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"]) posix_tests = ["POSIX", "POSIX-APPEND", "POSIX-SYMLINK-ACL", "POSIX-SYMLINK-EA", "POSIX-OFD-LOCK", - "POSIX-STREAM-DELETE", "WINDOWS-BAD-SYMLINK" ] + "POSIX-STREAM-DELETE", "WINDOWS-BAD-SYMLINK", "POSIX-MKDIR" ] for t in posix_tests: plantestsuite("samba3.smbtorture_s3.plain(nt4_dc).%s" % t, "nt4_dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/posix_share', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"]) diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 412e9b413fa..4959ed1f4f4 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -7254,6 +7254,105 @@ static bool run_posix_ofd_lock_test(int dummy) return correct; } +/* + Test POSIX mkdir is case-sensitive. + */ +static bool run_posix_mkdir_test(int dummy) +{ + static struct cli_state *cli; + const char *fname_foo = "POSIX_foo"; + const char *fname_foo_Foo = "POSIX_foo/Foo"; + const char *fname_foo_foo = "POSIX_foo/foo"; + const char *fname_Foo = "POSIX_Foo"; + const char *fname_Foo_Foo = "POSIX_Foo/Foo"; + const char *fname_Foo_foo = "POSIX_Foo/foo"; + bool correct = false; + NTSTATUS status; + TALLOC_CTX *frame = NULL; + + frame = talloc_stackframe(); + + printf("Starting POSIX mkdir test\n"); + + if (!torture_open_connection(&cli, 0)) { + TALLOC_FREE(frame); + return false; + } + + smbXcli_conn_set_sockopt(cli->conn, sockops); + + status = torture_setup_unix_extensions(cli); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return false; + } + + cli_posix_rmdir(cli, fname_foo_foo); + cli_posix_rmdir(cli, fname_foo_Foo); + cli_posix_rmdir(cli, fname_foo); + + cli_posix_rmdir(cli, fname_Foo_foo); + cli_posix_rmdir(cli, fname_Foo_Foo); + cli_posix_rmdir(cli, fname_Foo); + + status = cli_posix_mkdir(cli, fname_foo, 0777); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_mkdir of %s failed\n", fname_foo); + goto out; + } + + status = cli_posix_mkdir(cli, fname_Foo, 0777); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_mkdir of %s failed\n", fname_Foo); + goto out; + } + + status = cli_posix_mkdir(cli, fname_foo_foo, 0777); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_mkdir of %s failed\n", fname_foo_foo); + goto out; + } + + status = cli_posix_mkdir(cli, fname_foo_Foo, 0777); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo); + goto out; + } + + status = cli_posix_mkdir(cli, fname_Foo_foo, 0777); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo); + goto out; + } + + status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo); + goto out; + } + + printf("POSIX mkdir test passed\n"); + correct = true; + + out: + + cli_posix_rmdir(cli, fname_foo_foo); + cli_posix_rmdir(cli, fname_foo_Foo); + cli_posix_rmdir(cli, fname_foo); + + cli_posix_rmdir(cli, fname_Foo_foo); + cli_posix_rmdir(cli, fname_Foo_Foo); + cli_posix_rmdir(cli, fname_Foo); + + if (!torture_close_connection(cli)) { + correct = false; + } + + TALLOC_FREE(frame); + return correct; +} + + static uint32_t open_attrs_table[] = { FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, @@ -11609,6 +11708,7 @@ static struct { {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0}, {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0}, {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0}, + {"POSIX-MKDIR", run_posix_mkdir_test, 0}, {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0}, {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0}, {"ASYNC-ECHO", run_async_echo, 0}, -- 2.17.1 From dc18079d44ca3aadba2b593be96dafea6d07693d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Feb 2019 12:26:01 -0800 Subject: [PATCH 2/5] smbd: SMB1-POSIX: Add missing info-level SMB_POSIX_PATH_OPEN for UCF_UNIX_NAME_LOOKUP flag. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit 980db8debde68f9edce13fc01bc45a904379cffd) --- source3/smbd/trans2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e7a6e051e5b..0ec1c5f2a6a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -8830,6 +8830,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, if (info_level == SMB_SET_FILE_UNIX_BASIC || info_level == SMB_SET_FILE_UNIX_INFO2 || info_level == SMB_FILE_RENAME_INFORMATION || + info_level == SMB_POSIX_PATH_OPEN || info_level == SMB_POSIX_PATH_UNLINK) { ucf_flags |= UCF_UNIX_NAME_LOOKUP; } -- 2.17.1 From bac792765b6a1c9e682448f73ded631211e7eef1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Feb 2019 12:24:31 -0800 Subject: [PATCH 3/5] smbd: unix_convert: Ensure we don't call get_real_filename on POSIX paths. For posix_pathnames don't blunder into the name_has_wildcard OR get_real_filename() codepaths as they may be doing case insensitive lookups. So when creating a new POSIX directory 'Foo' they might match on name 'foo'. Remove POSIX-MKDIR from knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Sun Feb 24 14:04:14 CET 2019 on sn-devel-144 (cherry picked from commit 12da33e2bbce657f25abe9bc4cb936ca4615b30f) --- selftest/knownfail | 1 - source3/smbd/filename.c | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/selftest/knownfail b/selftest/knownfail index 951fbdd758e..baf3d57a31a 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -9,7 +9,6 @@ ^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.smbtorture_s3.*.POSIX-MKDIR ^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 diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ffc33f30c70..d4059956b4a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -906,6 +906,31 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, /* Stat failed - ensure we don't use it. */ SET_STAT_INVALID(smb_fname->st); + if (posix_pathnames) { + /* + * For posix_pathnames, we're done. + * Don't blunder into the name_has_wildcard OR + * get_real_filename() codepaths as they may + * be doing case insensitive lookups. So when + * creating a new POSIX directory Foo they might + * match on name foo. + * + * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803 + */ + if (errno == ENOENT) { + /* New file or directory. */ + goto done; + } + if ((errno == EACCES) && + (ucf_flags & UCF_PREP_CREATEFILE)) { + /* POSIX Dropbox case. */ + errno = 0; + goto done; + } + status = map_nt_error_from_unix(errno); + goto fail; + } + /* * Reset errno so we can detect * directory open errors. -- 2.17.1 From c9df67467b841c4b16b54d88a3a1e04159b734ef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 24 Feb 2019 08:03:32 -0800 Subject: [PATCH 4/5] s3: torture: Add additional POSIX mkdir tests. Ensure that if POSIX_foo exists as a file we return the correct error code NT_STATUS_OBJECT_PATH_NOT_FOUND if we try and traverse it as a directory. Also ensure creation/deletion of POSIX_foo/foo fails for directories and files with NT_STATUS_OBJECT_PATH_NOT_FOUND if the directory POSIX_foo/ doesn't exist. knownfail is back :-). BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit 632d0db8c42d50f5eecd002d9573f739cd945960) --- selftest/knownfail | 1 + source3/torture/torture.c | 102 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index baf3d57a31a..951fbdd758e 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -9,6 +9,7 @@ ^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.smbtorture_s3.*.POSIX-MKDIR ^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 diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 4959ed1f4f4..4e4f3760ddf 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -7269,6 +7269,7 @@ static bool run_posix_mkdir_test(int dummy) bool correct = false; NTSTATUS status; TALLOC_CTX *frame = NULL; + uint16_t fnum = (uint16_t)-1; frame = talloc_stackframe(); @@ -7295,6 +7296,102 @@ static bool run_posix_mkdir_test(int dummy) cli_posix_rmdir(cli, fname_Foo_Foo); cli_posix_rmdir(cli, fname_Foo); + /* + * Create a file POSIX_foo then try + * and use it in a directory path by + * doing mkdir POSIX_foo/bar. + * The mkdir should fail with + * NT_STATUS_OBJECT_PATH_NOT_FOUND + */ + + status = cli_posix_open(cli, + fname_foo, + O_RDWR|O_CREAT, + 0666, + &fnum); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_open of %s failed error %s\n", + fname_foo, + nt_errstr(status)); + goto out; + } + + status = cli_posix_mkdir(cli, fname_foo_foo, 0777); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { + printf("cli_posix_mkdir of %s should fail with " + "NT_STATUS_OBJECT_PATH_NOT_FOUND got " + "%s instead\n", + fname_foo_foo, + nt_errstr(status)); + goto out; + } + + status = cli_close(cli, fnum); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_close failed %s\n", nt_errstr(status)); + goto out; + } + fnum = (uint16_t)-1; + + status = cli_posix_unlink(cli, fname_foo); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_unlink of %s failed error %s\n", + fname_foo, + nt_errstr(status)); + goto out; + } + + /* + * Now we've deleted everything, posix_mkdir, posix_rmdir, + * posix_open, posix_unlink, on + * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND + * not silently create POSIX_foo/foo. + */ + + status = cli_posix_mkdir(cli, fname_foo_foo, 0777); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { + printf("cli_posix_mkdir of %s should fail with " + "NT_STATUS_OBJECT_PATH_NOT_FOUND got " + "%s instead\n", + fname_foo_foo, + nt_errstr(status)); + goto out; + } + + status = cli_posix_rmdir(cli, fname_foo_foo); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { + printf("cli_posix_rmdir of %s should fail with " + "NT_STATUS_OBJECT_PATH_NOT_FOUND got " + "%s instead\n", + fname_foo_foo, + nt_errstr(status)); + goto out; + } + + status = cli_posix_open(cli, + fname_foo_foo, + O_RDWR|O_CREAT, + 0666, + &fnum); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { + printf("cli_posix_open of %s should fail with " + "NT_STATUS_OBJECT_PATH_NOT_FOUND got " + "%s instead\n", + fname_foo_foo, + nt_errstr(status)); + goto out; + } + + status = cli_posix_unlink(cli, fname_foo_foo); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { + printf("cli_posix_unlink of %s should fail with " + "NT_STATUS_OBJECT_PATH_NOT_FOUND got " + "%s instead\n", + fname_foo_foo, + nt_errstr(status)); + goto out; + } + status = cli_posix_mkdir(cli, fname_foo, 0777); if (!NT_STATUS_IS_OK(status)) { printf("cli_posix_mkdir of %s failed\n", fname_foo); @@ -7336,6 +7433,11 @@ static bool run_posix_mkdir_test(int dummy) out: + if (fnum != (uint16_t)-1) { + cli_close(cli, fnum); + fnum = (uint16_t)-1; + } + cli_posix_rmdir(cli, fname_foo_foo); cli_posix_rmdir(cli, fname_foo_Foo); cli_posix_rmdir(cli, fname_foo); -- 2.17.1 From f982cb1d97ad579c28118ae24053194f4e16f2cf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 24 Feb 2019 08:15:23 -0800 Subject: [PATCH 5/5] s3: smbd: filenames - ensure we replace the missing '/' if we error in an intermediate POSIX path. Previous regression test ensures we still return the correct error code for POSIX pathname operations. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Mon Feb 25 09:33:27 CET 2019 on sn-devel-144 (cherry picked from commit 3f1a13a94a753c5cb3b9f2cf795df5adb0f74205) --- selftest/knownfail | 1 - source3/smbd/filename.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/selftest/knownfail b/selftest/knownfail index 951fbdd758e..baf3d57a31a 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -9,7 +9,6 @@ ^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.smbtorture_s3.*.POSIX-MKDIR ^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 diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d4059956b4a..40caf951cca 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -917,6 +917,24 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803 */ + if (end != NULL) { + const char *morepath = NULL; + /* + * If this is intermediate we must + * restore the full path. + */ + *end = '/'; + /* + * If there are any more components + * after the failed LSTAT we cannot + * continue. + */ + morepath = strchr(end + 1, '/'); + if (morepath != NULL) { + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; + } + } if (errno == ENOENT) { /* New file or directory. */ goto done; -- 2.17.1