[SCM] Samba Shared Repository - branch master updated
Stefan Metzmacher
metze at samba.org
Mon Aug 22 09:04:01 UTC 2022
The branch, master has been updated
via 75e03ea021a libcli/smb: Set error status if 'iov' pointer is NULL
via 40d4912d841 libcli/smb: Ensure we call tevent_req_nterror() on failure
via 968a5ae89f0 smbd: directly pass fsp to SMB_VFS_FGETXATTR() in fget_ea_dos_attribute()
via 3f7d8db9945 smbd: add and use vfs_fget_dos_attributes()
via e74b10e17ee smbtorture: add test smb2.stream.attributes2
via b5848d391be smbtorture: rename smb2.streams.attributes to smb2.streams.attributes1
from d4f18f99d3a s3:smbd: let delay_for_oplock_fn() only call leases_db_get() once
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 75e03ea021afa66842b6e0dea21072b1b8026d58
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date: Mon Aug 22 16:56:46 2022 +1200
libcli/smb: Set error status if 'iov' pointer is NULL
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15152
Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
Autobuild-Date(master): Mon Aug 22 09:03:29 UTC 2022 on sn-devel-184
commit 40d4912d841e6bcd7cd37810ef101d5f89268ee7
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date: Mon Aug 22 15:50:02 2022 +1200
libcli/smb: Ensure we call tevent_req_nterror() on failure
Commit 3594c3ae202688fd8aae5f7f5e20464cb23feea9 added a NULL check for
'inhdr', but it meant we didn't always call tevent_req_nterror() when we
should.
Now we handle connection errors. We now also set an error status if the
NULL check fails.
I noticed this when an ECONNRESET error from a server refusing SMB1
wasn't handled, and the client subsequently hung in epoll_wait().
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15152
Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit 968a5ae89f0d0da219e7dd05dd1f7f7c96dbb910
Author: Ralph Boehme <slow at samba.org>
Date: Sun Aug 14 16:39:37 2022 +0200
smbd: directly pass fsp to SMB_VFS_FGETXATTR() in fget_ea_dos_attribute()
We're now consistently passing the base_fsp to SMB_VFS_FSET_DOS_ATTRIBUTES(), so
we don't need to check for a stream_fsp here anymore.
Additionally vfs_default will assert a non-stream fsp inside
vfswrap_fgetxattr(), so in case any caller wrongly passes a stream fsp, this is
caught in vfs_default.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126
MR: https://gitlab.com/samba-team/samba/-/merge_requests/2643
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit 3f7d8db9945a325020e4d1574289dea9e8331c29
Author: Ralph Boehme <slow at samba.org>
Date: Thu Aug 11 17:18:13 2022 +0200
smbd: add and use vfs_fget_dos_attributes()
Commit d71ef1365cdde47aeb3465699181656b0655fa04 caused a regression where the
creation date on streams wasn't updated anymore on the stream fsp.
By adding a simple wrapper vfs_fget_dos_attributes() that takes care of
- passing only the base_fsp to the VFS, so the VFS can be completely agnostic of
all the streams related complexity like fake fds,
- propagating any updated btime from the base_fsp->fsp_name to the
stream_fsp->fsp_name
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126
MR: https://gitlab.com/samba-team/samba/-/merge_requests/2643
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit e74b10e17ee5df0f77ac5349242841be8d71c4e8
Author: Ralph Boehme <slow at samba.org>
Date: Sat Aug 13 16:13:07 2022 +0200
smbtorture: add test smb2.stream.attributes2
Specifically torture the creation date is the same for the file and its streams.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126
MR: https://gitlab.com/samba-team/samba/-/merge_requests/2643
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit b5848d391be4f7633745d9c36e432ac8b1c9dba2
Author: Ralph Boehme <slow at samba.org>
Date: Sat Aug 13 17:04:50 2022 +0200
smbtorture: rename smb2.streams.attributes to smb2.streams.attributes1
A subsequent commit adds another streams test named "attributes2", this change
avoids matching the new testname with the existing knownfail entries.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126
MR: https://gitlab.com/samba-team/samba/-/merge_requests/2643
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
-----------------------------------------------------------------------
Summary of changes:
libcli/smb/smbXcli_base.c | 12 +-
selftest/knownfail | 4 +-
source3/include/proto.h | 3 +
source3/smbd/dosmode.c | 7 +-
source3/smbd/open.c | 3 +-
source3/smbd/vfs.c | 39 +++++
source4/torture/smb2/streams.c | 361 ++++++++++++++++++++++++++++++++++++++++-
7 files changed, 416 insertions(+), 13 deletions(-)
Changeset truncated at 500 lines:
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index d2f55966c3a..c5d13bd5837 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -4469,7 +4469,11 @@ static void smbXcli_negprot_smb1_done(struct tevent_req *subreq)
NULL, /* pinbuf */
expected, ARRAY_SIZE(expected));
TALLOC_FREE(subreq);
- if (inhdr == NULL || tevent_req_nterror(req, status)) {
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ if (inhdr == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
}
@@ -5009,7 +5013,11 @@ static void smbXcli_negprot_smb2_done(struct tevent_req *subreq)
status = smb2cli_req_recv(subreq, state, &iov,
expected, ARRAY_SIZE(expected));
- if (tevent_req_nterror(req, status) || iov == NULL) {
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ if (iov == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
}
diff --git a/selftest/knownfail b/selftest/knownfail
index 173286a96a0..0b4c5a44a7f 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -207,10 +207,10 @@
^samba3.smb2.oplock.stream1
^samba3.smb2.streams.rename
^samba3.smb2.streams.rename2
-^samba3.smb2.streams.attributes
+^samba3.smb2.streams.attributes1\(.*\)
^samba3.smb2.streams streams_xattr.rename\(nt4_dc\)
^samba3.smb2.streams streams_xattr.rename2\(nt4_dc\)
-^samba3.smb2.streams streams_xattr.attributes\(nt4_dc\)
+^samba3.smb2.streams streams_xattr.attributes1\(nt4_dc\)
^samba3.smb2.getinfo.complex
^samba3.smb2.getinfo.fsinfo # quotas don't work yet
^samba3.smb2.setinfo.setinfo
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 6a6edc36dfb..f632cf37c08 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -82,6 +82,9 @@ NTSTATUS vfs_at_fspcwd(TALLOC_CTX *mem_ctx,
struct connection_struct *conn,
struct files_struct **_fsp);
+NTSTATUS vfs_fget_dos_attributes(struct files_struct *fsp,
+ uint32_t *dosmode);
+
#include "source3/lib/interface.h"
/* The following definitions come from lib/ldap_debug_handler.c */
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 3d69a35b366..cb3cdc568bd 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -366,7 +366,7 @@ NTSTATUS fget_ea_dos_attribute(struct files_struct *fsp,
/* Don't reset pattr to zero as we may already have filename-based attributes we
need to preserve. */
- sizeret = SMB_VFS_FGETXATTR(fsp->base_fsp ? fsp->base_fsp : fsp,
+ sizeret = SMB_VFS_FGETXATTR(fsp,
SAMBA_XATTR_DOS_ATTRIB,
attrstr,
sizeof(attrstr));
@@ -377,7 +377,7 @@ NTSTATUS fget_ea_dos_attribute(struct files_struct *fsp,
rights than the real user
*/
become_root();
- sizeret = SMB_VFS_FGETXATTR(fsp->base_fsp ? fsp->base_fsp : fsp,
+ sizeret = SMB_VFS_FGETXATTR(fsp,
SAMBA_XATTR_DOS_ATTRIB,
attrstr,
sizeof(attrstr));
@@ -727,8 +727,7 @@ uint32_t fdos_mode(struct files_struct *fsp)
}
/* Get the DOS attributes via the VFS if we can */
- status = SMB_VFS_FGET_DOS_ATTRIBUTES(
- fsp->conn, metadata_fsp(fsp), &result);
+ status = vfs_fget_dos_attributes(fsp, &result);
if (!NT_STATUS_IS_OK(status)) {
/*
* Only fall back to using UNIX modes if we get NOT_IMPLEMENTED.
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d5c2f4c830f..3dd9f69b8cc 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -3651,8 +3651,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
*/
uint32_t attr = 0;
- status = SMB_VFS_FGET_DOS_ATTRIBUTES(
- conn, metadata_fsp(smb_fname->fsp), &attr);
+ status = vfs_fget_dos_attributes(smb_fname->fsp, &attr);
if (NT_STATUS_IS_OK(status)) {
existing_dos_attributes = attr;
}
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 09be625ab5f..5833d1b2ab2 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -1509,6 +1509,45 @@ NTSTATUS vfs_at_fspcwd(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+NTSTATUS vfs_fget_dos_attributes(struct files_struct *fsp,
+ uint32_t *dosmode)
+{
+ NTSTATUS status;
+
+ /*
+ * First make sure to pass the base_fsp to the VFS
+ */
+ status = SMB_VFS_FGET_DOS_ATTRIBUTES(
+ fsp->conn, metadata_fsp(fsp), dosmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /*
+ * If this isn't a stream fsp we're done, ...
+ */
+ if (!fsp_is_alternate_stream(fsp)) {
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * ...otherwise the VFS might have updated the btime, propagate the
+ * btime from the base_fsp to the stream fsp.
+ */
+
+ if (fsp->base_fsp->fsp_name->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME) {
+ /*
+ * Not a value from backend storage, ignore it
+ */
+ return NT_STATUS_OK;
+ }
+
+ update_stat_ex_create_time(&fsp->fsp_name->st,
+ fsp->base_fsp->fsp_name->st.st_ex_btime);
+
+ return NT_STATUS_OK;
+}
+
int smb_vfs_call_connect(struct vfs_handle_struct *handle,
const char *service, const char *user)
{
diff --git a/source4/torture/smb2/streams.c b/source4/torture/smb2/streams.c
index dee8f8afc9d..f18048f7762 100644
--- a/source4/torture/smb2/streams.c
+++ b/source4/torture/smb2/streams.c
@@ -23,6 +23,7 @@
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
+#include "smb_constants.h"
#include "torture/torture.h"
#include "torture/smb2/proto.h"
@@ -1804,8 +1805,8 @@ static bool open_stream(struct smb2_tree *tree,
/* Test the effect of setting attributes on a stream. */
-static bool test_stream_attributes(struct torture_context *tctx,
- struct smb2_tree *tree)
+static bool test_stream_attributes1(struct torture_context *tctx,
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
bool ret = true;
@@ -1960,6 +1961,359 @@ done:
return ret;
}
+static bool check_metadata(struct torture_context *tctx,
+ struct smb2_tree *tree,
+ const char *path,
+ struct smb2_handle _h,
+ NTTIME expected_btime,
+ uint32_t expected_attribs)
+{
+ struct smb2_handle h = _h;
+ union smb_fileinfo getinfo;
+ NTSTATUS status;
+ bool ret = true;
+
+ if (smb2_util_handle_empty(h)) {
+ struct smb2_create c;
+
+ c = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = FILE_ATTRIBUTE_HIDDEN,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = path,
+ };
+ status = smb2_create(tree, tctx, &c);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+
+ h = c.out.file.handle;
+ }
+
+ getinfo = (union smb_fileinfo) {
+ .generic.level = SMB_QFILEINFO_BASIC_INFORMATION,
+ .generic.in.file.handle = h,
+ };
+
+ status = smb2_getinfo_file(tree, tctx, &getinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed\n");
+
+ torture_assert_u64_equal_goto(tctx,
+ expected_btime,
+ getinfo.basic_info.out.create_time,
+ ret, done,
+ "btime was updated\n");
+
+ torture_assert_u32_equal_goto(tctx,
+ expected_attribs,
+ getinfo.basic_info.out.attrib,
+ ret, done,
+ "btime was updated\n");
+
+done:
+ if (smb2_util_handle_empty(_h)) {
+ smb2_util_close(tree, h);
+ }
+
+ return ret;
+}
+
+static bool test_stream_attributes2(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ struct smb2_create c1;
+ struct smb2_handle h1 = {{0}};
+ const char *fname = DNAME "\\test_stream_btime";
+ const char *sname = DNAME "\\test_stream_btime:stream";
+ union smb_fileinfo getinfo;
+ union smb_setfileinfo setinfo;
+ const char *data = "test data";
+ struct timespec ts;
+ NTTIME btime;
+ uint32_t attrib = FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_ARCHIVE;
+ bool ret;
+
+ smb2_deltree(tree, DNAME);
+
+ status = torture_smb2_testdir(tree, DNAME, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir failed\n");
+ smb2_util_close(tree, h1);
+
+ torture_comment(tctx, "Let's dance!\n");
+
+ /*
+ * Step 1: create file and get creation date
+ */
+
+ c1 = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = FILE_ATTRIBUTE_HIDDEN,
+ .in.create_disposition = NTCREATEX_DISP_CREATE,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = fname,
+ };
+ status = smb2_create(tree, tctx, &c1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ h1 = c1.out.file.handle;
+
+ getinfo = (union smb_fileinfo) {
+ .generic.level = SMB_QFILEINFO_BASIC_INFORMATION,
+ .generic.in.file.handle = h1,
+ };
+ status = smb2_getinfo_file(tree, tctx, &getinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed\n");
+
+ btime = getinfo.basic_info.out.create_time;
+
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ ZERO_STRUCT(h1);
+
+ /*
+ * Step X: write to file, assert btime was not updated
+ */
+
+ c1 = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = attrib,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = fname,
+ };
+ status = smb2_create(tree, tctx, &c1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ h1 = c1.out.file.handle;
+
+ status = smb2_util_write(tree, h1, data, 0, strlen(data));
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ ret = check_metadata(tctx, tree, NULL, h1, btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ ZERO_STRUCT(h1);
+
+ ret = check_metadata(tctx, tree, fname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ /*
+ * Step X: create stream, assert creation date is the same
+ * as the one on the basefile
+ */
+
+ c1 = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = attrib,
+ .in.create_disposition = NTCREATEX_DISP_CREATE,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = sname,
+ };
+ status = smb2_create(tree, tctx, &c1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ h1 = c1.out.file.handle;
+
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ ZERO_STRUCT(h1);
+
+ ret = check_metadata(tctx, tree, sname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ /*
+ * Step X: set btime on stream, verify basefile has the same btime.
+ */
+
+ c1 = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = attrib,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = sname,
+ };
+ status = smb2_create(tree, tctx, &c1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ h1 = c1.out.file.handle;
+
+ setinfo = (union smb_setfileinfo) {
+ .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
+ .basic_info.in.file.handle = h1,
+ };
+ clock_gettime_mono(&ts);
+ btime = setinfo.basic_info.in.create_time = full_timespec_to_nt_time(&ts);
+
+ status = smb2_setinfo_file(tree, &setinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_setinfo_file failed\n");
+
+ ret = check_metadata(tctx, tree, NULL, h1, btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad time on stream\n");
+
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ ZERO_STRUCT(h1);
+
+ ret = check_metadata(tctx, tree, fname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad time on basefile\n");
+
+ ret = check_metadata(tctx, tree, sname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad time on stream\n");
+
+ /*
+ * Step X: write to stream, assert btime was not updated
+ */
+
+ c1 = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = attrib,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = sname,
+ };
+ status = smb2_create(tree, tctx, &c1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ h1 = c1.out.file.handle;
+
+ status = smb2_util_write(tree, h1, data, 0, strlen(data));
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ ret = check_metadata(tctx, tree, NULL, h1, btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ ZERO_STRUCT(h1);
+
+ ret = check_metadata(tctx, tree, fname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ ret = check_metadata(tctx, tree, sname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ /*
+ * Step X: modify attributes via stream, verify it's "also" set on the
+ * basefile.
+ */
+
+ c1 = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = attrib,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = sname,
+ };
+ status = smb2_create(tree, tctx, &c1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ h1 = c1.out.file.handle;
+
+ attrib = FILE_ATTRIBUTE_NORMAL;
+
+ setinfo = (union smb_setfileinfo) {
+ .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
+ .basic_info.in.file.handle = h1,
+ .basic_info.in.attrib = attrib,
+ };
+
+ status = smb2_setinfo_file(tree, &setinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_setinfo_file failed\n");
+
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ ZERO_STRUCT(h1);
+
+ ret = check_metadata(tctx, tree, fname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ ret = check_metadata(tctx, tree, sname, (struct smb2_handle){{0}},
+ btime, attrib);
+ torture_assert_goto(tctx, ret, ret, done, "Bad metadata\n");
+
+ /*
+ * Step X: modify attributes via basefile, verify it's "also" set on the
+ * stream.
+ */
+
+ c1 = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = attrib,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
+ .in.fname = fname,
+ };
+ status = smb2_create(tree, tctx, &c1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
--
Samba Shared Repository
More information about the samba-cvs
mailing list