From 5245abc514c031d39c5961234dae3e4219a2185e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Oct 2022 13:14:41 -0700 Subject: [PATCH 1/2] s4: torture: libsmbclient: Add a torture test to ensure smbc_stat() returns ENOENT on a non-existent file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15195 Signed-off-by: Jeremy Allison Reviewed-by: Pavel Filipenský (cherry picked from commit 9eda432836bfff3d3d4a365a08a5ecb54f0f2e34) --- selftest/knownfail.d/libsmb_getatr | 2 + source4/torture/libsmbclient/libsmbclient.c | 63 +++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 selftest/knownfail.d/libsmb_getatr diff --git a/selftest/knownfail.d/libsmb_getatr b/selftest/knownfail.d/libsmb_getatr new file mode 100644 index 00000000000..d5fd1e9df3e --- /dev/null +++ b/selftest/knownfail.d/libsmb_getatr @@ -0,0 +1,2 @@ +^samba4.libsmbclient.getatr.NT1.getatr\(nt4_dc_smb1_done\) +^samba4.libsmbclient.getatr.SMB3.getatr\(nt4_dc\) diff --git a/source4/torture/libsmbclient/libsmbclient.c b/source4/torture/libsmbclient/libsmbclient.c index b04dbde04ac..48a624cb7e2 100644 --- a/source4/torture/libsmbclient/libsmbclient.c +++ b/source4/torture/libsmbclient/libsmbclient.c @@ -1412,6 +1412,67 @@ static bool torture_libsmbclient_rename(struct torture_context *tctx) return success; } +static bool torture_libsmbclient_getatr(struct torture_context *tctx) +{ + const char *smburl = torture_setting_string(tctx, "smburl", NULL); + SMBCCTX *ctx = NULL; + char *getatr_name = NULL; + struct stat st = {0}; + bool ok; + int ret = 0; + int err = 0; + + if (smburl == NULL) { + torture_fail(tctx, + "option --option=torture:smburl=" + "smb://user:password@server missing\n"); + } + + ok = torture_libsmbclient_init_context(tctx, &ctx); + torture_assert(tctx, ok, "Failed to init context"); + smbc_set_context(ctx); + + getatr_name = talloc_asprintf(tctx, + "%s/noexist", + smburl); + if (getatr_name == NULL) { + torture_result(tctx, + TORTURE_FAIL, + __location__": %s", + "talloc fail\n"); + return false; + } + /* Ensure the file doesn't exist. */ + smbc_unlink(getatr_name); + /* + * smbc_stat() internally uses SMBC_getatr(). + * Make sure doing getatr on a non-existent file gives + * an error of -1, errno = ENOENT. + */ + + ret = smbc_stat(getatr_name, &st); + if (ret == -1) { + err = errno; + } + torture_assert_int_equal(tctx, + ret, + -1, + talloc_asprintf(tctx, + "smbc_stat on '%s' should " + "get -1, got %d\n", + getatr_name, + ret)); + torture_assert_int_equal(tctx, + err, + ENOENT, + talloc_asprintf(tctx, + "smbc_stat on '%s' should " + "get errno = ENOENT, got %s\n", + getatr_name, + strerror(err))); + return true; +} + NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx) { struct torture_suite *suite; @@ -1438,6 +1499,8 @@ NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx) torture_suite_add_simple_test(suite, "rename", torture_libsmbclient_rename); + torture_suite_add_simple_test(suite, "getatr", + torture_libsmbclient_getatr); suite->description = talloc_strdup(suite, "libsmbclient interface tests"); -- 2.34.1 From b06293420dafd8fd04c0965bdf7ab232885f7c39 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Oct 2022 13:24:27 -0700 Subject: [PATCH 2/2] s3: libsmbclient: Fix smbc_stat() to return ENOENT on a non-existent file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15195 Signed-off-by: Jeremy Allison Reviewed-by: Pavel Filipenský Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Oct 19 00:13:56 UTC 2022 on sn-devel-184 (cherry picked from commit fd0c01da1c744ae6fd9d8675616d8b6d3531e469) --- source3/libsmb/libsmb_file.c | 39 +++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 0332b926610..ef6f757a434 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -463,6 +463,7 @@ SMBC_getatr(SMBCCTX * context, struct timespec access_time_ts = {0}; struct timespec write_time_ts = {0}; struct timespec change_time_ts = {0}; + struct timespec w_time_ts = {0}; time_t write_time = 0; SMB_INO_T ino = 0; struct cli_credentials *creds = NULL; @@ -503,12 +504,13 @@ SMBC_getatr(SMBCCTX * context, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Couldn't resolve %s\n", path); - errno = ENOENT; TALLOC_FREE(frame); + errno = cli_status_to_errno(status); return False; } if (!srv->no_pathinfo2) { + bool not_supported_error = false; status = cli_qpathinfo2(targetcli, targetpath, &create_time_ts, @@ -521,11 +523,22 @@ SMBC_getatr(SMBCCTX * context, if (NT_STATUS_IS_OK(status)) { goto setup_stat; } + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL) || + NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + not_supported_error = true; + } + if (!not_supported_error) { + /* "Normal error". Just return it to caller. */ + TALLOC_FREE(frame); + errno = cli_status_to_errno(status); + return false; + } } srv->no_pathinfo2 = True; if (!srv->no_pathinfo3) { + bool not_supported_error = false; status = cli_qpathinfo3(targetcli, targetpath, &create_time_ts, @@ -538,24 +551,32 @@ SMBC_getatr(SMBCCTX * context, if (NT_STATUS_IS_OK(status)) { goto setup_stat; } + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL) || + NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + not_supported_error = true; + } + if (!not_supported_error) { + /* "Normal error". Just return it to caller. */ + TALLOC_FREE(frame); + errno = cli_status_to_errno(status); + return false; + } } srv->no_pathinfo3 = True; /* if this is NT then don't bother with the getatr */ if (smb1cli_conn_capabilities(targetcli->conn) & CAP_NT_SMBS) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; goto all_failed; } status = cli_getatr(targetcli, targetpath, &attr, &size, &write_time); - if (NT_STATUS_IS_OK(status)) { - struct timespec w_time_ts = - convert_time_t_to_timespec(write_time); - - access_time_ts = change_time_ts = write_time_ts = w_time_ts; - - goto setup_stat; + if (!NT_STATUS_IS_OK(status)) { + goto all_failed; } + w_time_ts = convert_time_t_to_timespec(write_time); + access_time_ts = change_time_ts = write_time_ts = w_time_ts; setup_stat: setup_stat(sb, @@ -575,8 +596,8 @@ all_failed: srv->no_pathinfo2 = False; srv->no_pathinfo3 = False; - errno = EPERM; TALLOC_FREE(frame); + errno = cli_status_to_errno(status); return False; } -- 2.34.1