[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