[cifs-protocol] [REG:117102016529426] SMB2 File Rename

Uri Simchoni uri at samba.org
Wed Oct 25 19:52:16 UTC 2017


Chiming in because I also had rename-related investigations (I don't
think this answers the original question but it is relevant to the
response):
- smbclient does SMB1 rename using cifs rename, not using FILE_RENAME_INFO
- so does Windows (or so it seems)
- smbclient can be made to use FILE_RENAME_INFO using the -f option
- however, the -f implementation for NT1 is broken because NT1 expects
the dest file to be relative to directory of source file, and cannot
move it to another dir (SMB2 onwards expects the dest to be relative to
share's root and *can* move file between dirs

The attached patch set to Samba includes a torture test that
demonstrates all that (passes against both Samba and Windows 10)

Thanks,
Uri.

On 10/25/2017 10:18 PM, Sreekanth Nadendla via cifs-protocol wrote:
> Hello Andreas, in the sample traces you've sent us, I can see the setInfo request with SMB2_FILE_RENAME_INFO for SMB2 case. However I don't see similar rename structure from your first trace rename_nt1.  Let me know if I'm missing something. 
> 
> On windows OS, rename command does not allow you to specify a new drive (device) or *path* for the destination file. Before I dig in further with "move" command in my investigation, I would like to see from your traces exactly how the request was sent to server in the case of SMB v1.  Also if you can, please confirm if the same Windows 2012 server is used when your client was using SMB v3.
> 
> 
> Regards,
> Sreekanth Nadendla
> Microsoft Windows Open Specifications
> 
> -----Original Message-----
> From: Sreekanth Nadendla 
> Sent: Friday, October 20, 2017 11:16 AM
> To: Andreas Schneider <asn at samba.org>
> Cc: cifs-protocol at lists.samba.org; MSSolve Case Email <casemail at microsoft.com>
> Subject: [REG:117102016529426] SMB2 File Rename
> 
> Hello Andreas, I will be assisting you with your issue. I am currently researching the problem and will provide you with an update soon. Thank you for your patience.
> 
> Regards,
> Sreekanth Nadendla
> Microsoft Windows Open Specifications
> 
> -----Original Message-----
> From: Andreas Schneider [mailto:asn at samba.org]
> Sent: Friday, October 20, 2017 6:21 AM
> To: Interoperability Documentation Help <dochelp at microsoft.com>
> Cc: cifs-protocol at lists.samba.org
> Subject: SMB2 File Rename
> 
> Hello,
> 
> I disovered that a file rename operation (SetInfo with
> FILE_RENAME_INFORMATION_TYPE_2) fails for a SMB3 connection but works for SMB1.
> 
> I've run smbclient from Samba again Windows 2012:
> 
> File rename (move) over SMB1 with smbclient:
> 
> bin/smbclient //win-dc02.earth.milkyway.site/Test -Ubob1%Secret007! -mNT1 Try "help" to get a list of possible commands.
> smb: \> cd dir1
> smb: \dir1\> rename README ..\dir2\README
> smb: \dir1\>
> 
> This works!
> 
> File rename (move) over SMB3 with smbclient:
> 
> bin/smbclient //win-dc02.earth.milkyway.site/Test -Ubob1%Secret007! -mSMB3 Try "help" to get a list of possible commands.
> smb: \> cd dir1
> smb: \dir1\> rename README ..\dir2\README NT_STATUS_OBJECT_NAME_NOT_FOUND renaming files \dir1\README -> \dir1\..
> \dir2\README
> smb: \dir1\>
> 
> As you can see, it fails with NT_STATUS_OBJECT_NAME_NOT_FOUND.
> 
> I do not see that we're doing anything wrong in the SetInfo request. The doc does not mention that '..' is not allowed.
> 
> Is a path of dir1\..\dir2\file not allowed?
> 
> 
> Attached are the network traces.
> 
> 
> Thanks for your help!
> 
> 
> Best regards,
> 
> 
> Andreas
> 
> 

-------------- next part --------------
From c5c185f510eee0729b5b6abeb5209c89ac3537fd Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at vfunction.com>
Date: Thu, 7 Sep 2017 18:12:25 +0300
Subject: [PATCH 1/3] cli: add low-level synchronous NT1 rename

Add a synchronous function that invokes rename via
FILE_RENAME_INFORMATION passthrough, in the NT1
dialect. This adds on the async version that already
exists, and is meant for use by torture tests.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/libsmb/clifile.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 source3/libsmb/proto.h   |  4 ++++
 2 files changed, 51 insertions(+)

diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index a6a0baf..548c99e 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -1094,6 +1094,53 @@ fail:
 	return tevent_req_post(req, ev);
 }
 
+NTSTATUS cli_smb1_rename(struct cli_state *cli,
+		    const char *fname_src,
+		    const char *fname_dst,
+		    bool replace)
+{
+	TALLOC_CTX *frame = NULL;
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_OK;
+
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	frame = talloc_stackframe();
+
+	if (smbXcli_conn_has_async_calls(cli->conn)) {
+		/*
+		 * Can't use sync call while an async call is in flight
+		 */
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto fail;
+	}
+
+	ev = samba_tevent_context_init(frame);
+	if (ev == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto fail;
+	}
+
+	req = cli_smb1_rename_send(frame, ev, cli, fname_src, fname_dst, replace);
+	if (req == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto fail;
+	}
+
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+
+	status = cli_rename_recv(req);
+
+ fail:
+	TALLOC_FREE(frame);
+	return status;
+}
+
 static void cli_smb1_rename_done(struct tevent_req *subreq)
 {
 	NTSTATUS status = cli_setpathinfo_recv(subreq);
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 4ae566c..03dd53b 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -344,6 +344,10 @@ NTSTATUS cli_rename(struct cli_state *cli,
 		    const char *fname_src,
 		    const char *fname_dst,
 		    bool replace);
+NTSTATUS cli_smb1_rename(struct cli_state *cli,
+		    const char *fname_src,
+		    const char *fname_dst,
+		    bool replace);
 struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
                                 struct tevent_context *ev,
                                 struct cli_state *cli,
-- 
2.9.5


From 1a6e84301c31b0f3f38e77a28a91131e1c0d4ed4 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at vfunction.com>
Date: Wed, 18 Oct 2017 19:02:00 +0300
Subject: [PATCH 2/3] torture: add a low-level test for rename and replace

Add a torture test that renames files and supersedes existing
destination files, using FILE_RENAME_INFORMATION.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/torture/torture.c | 393 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 393 insertions(+)

diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 360adad..5c6fd32 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -5238,6 +5238,398 @@ static bool run_rename_access(int dummy)
 }
 
 /*
+  Test rename with replace (for NT1 dialect, that's
+  rename using FILE_RENAME_INFORMATION rather than
+  CIFS rename).
+
+  Notice the difference in semantics between NT1 and
+  SMB2/3:
+  - In NT1 protocol, the destination is relative to the source file,
+    and renames using this method are only allowed in the same directory.
+  - In SMB2 and later, the destination is relative to the share's root,
+    and can move files between directories.
+
+    In the Windows implementation, a directory rename which supersedes
+    an existing directory (even an empty one) is not allowed.
+ */
+static bool run_rename_replace(int dummy)
+{
+	static struct cli_state *cli1;
+	const char *fname = "test.txt";
+	const char *fname1 = "test1.txt";
+	const char *dname = "ren_subdir";
+	const char *dname1 = "ren_subdir1";
+	const char *indir = "ren_subdir\\test.txt";
+	const char *indir1 = "ren_subdir\\test1.txt";
+	const char *rename_dest = indir;
+	bool correct = true;
+	bool expect_rename_success = true;
+	bool is_smb2 = true;
+	uint16_t fnum1 = (uint16_t)-1;
+	NTSTATUS status;
+	uint8_t buf[10] = {0};
+	off_t fsize = 0;
+	NTSTATUS (*do_rename)(struct cli_state *cli,
+			      const char *fname_src,
+			      const char *fname_dst,
+			      bool replace) = cli_rename;
+
+	printf("starting rename replace test\n");
+
+	if (!torture_open_connection(&cli1, 0)) {
+		return false;
+	}
+
+	smbXcli_conn_set_sockopt(cli1->conn, sockops);
+
+	if (smbXcli_conn_protocol(cli1->conn) < PROTOCOL_SMB2_02) {
+		is_smb2 = false;
+		do_rename = cli_smb1_rename;
+	}
+
+	cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, indir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_rmdir(cli1, dname);
+	cli_unlink(cli1, indir1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_rmdir(cli1, dname);
+	cli_rmdir(cli1, dname1);
+
+	/*
+	 * rename (move) into a subdir using FILE_RENAME_INFORMATION
+	 * This works with SMB2 and fails with NT1
+	 */
+	status = cli_mkdir(cli1, dname);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("First test mkdir failed - %s\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
+			      FILE_ATTRIBUTE_NORMAL,
+			      FILE_SHARE_DELETE | FILE_SHARE_READ,
+			      FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("First open failed - %s\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	expect_rename_success = true;
+	if (!is_smb2) {
+		expect_rename_success = false;
+	}
+
+	status = do_rename(cli1, fname, indir, true);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("First rename failed %s - %s\n",
+		       expect_rename_success ? "- this should have succeeded"
+					     : "(this is correct)",
+		       nt_errstr(status));
+		if (expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	} else {
+		printf("First rename succeeded %s\n",
+		       expect_rename_success ? "(this is correct)"
+					     : "- this should have failed");
+		if (!expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	}
+
+	status = cli_getatr(cli1, indir, NULL, &fsize, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("First stat dest failed %s - %s\n",
+		       expect_rename_success ? "- this should have succeeded"
+					     : "(this is correct)",
+		       nt_errstr(status));
+		if (expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	} else {
+		printf("First stat dest succeeded %s\n",
+		       expect_rename_success ? "(this is correct)"
+					     : "- this should have failed");
+		if (!expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	}
+
+	status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("First stat src failed %s - %s\n",
+		       !expect_rename_success ? "- this should have succeeded"
+					      : "(this is correct)",
+		       nt_errstr(status));
+		if (!expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	} else {
+		printf("First stat src succeeded %s\n",
+		       !expect_rename_success ? "(this is correct)"
+					      : "- this should have failed");
+		if (expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	}
+
+	status = cli_close(cli1, fnum1);
+	fnum1 = (uint16_t)-1;
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("close - 1 failed (%s)\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, indir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_rmdir(cli1, dname);
+
+	/*
+	 * rename and replace using FILE_RENAME_INFORMATION, different
+	 * directories (supported by SMB2, not supported by NT1)
+	 */
+
+	expect_rename_success = true;
+	if (!is_smb2) {
+		expect_rename_success = false;
+	}
+
+	status = cli_mkdir(cli1, dname);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("2nd test mkdir failed - %s\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	/* set up a file whose length is 10 bytes - this will be
+	 * replaced by a zero-length file
+	 */
+	status = cli_ntcreate(cli1, indir1, 0, GENERIC_WRITE_ACCESS,
+			      FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+			      FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("2nd create to-replace file failed - %s\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	status = cli_writeall(cli1, fnum1, 0, buf, 0, sizeof(buf), NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("write - 2 - to-replace- failed (%s)\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	status = cli_close(cli1, fnum1);
+	fnum1 = (uint16_t)-1;
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("close - 2 - to-replace- failed (%s)\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	status = cli_getatr(cli1, indir1, NULL, &fsize, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("getatr - 2 - to-replace- failed (%s)\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	if ((size_t)fsize != sizeof(buf)) {
+		printf("getatr - 2 - to-replace- incorrect file size\n");
+		correct = false;
+		goto out;
+	}
+
+	status = cli_ntcreate(cli1, fname1, 0, GENERIC_READ_ACCESS,
+			      FILE_ATTRIBUTE_NORMAL,
+			      FILE_SHARE_DELETE | FILE_SHARE_READ,
+			      FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("2nd open failed - %s\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	status = do_rename(cli1, fname1, indir1, true);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("2nd rename failed %s - %s\n",
+		       expect_rename_success ? "- this should have succeeded"
+					     : "(this is correct)",
+		       nt_errstr(status));
+		if (expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	} else {
+		printf("2nd rename succeeded %s\n",
+		       expect_rename_success ? "(this is correct)"
+					     : "- this should have failed");
+		if (!expect_rename_success) {
+			correct = false;
+			goto out;
+		}
+	}
+
+	status = cli_close(cli1, fnum1);
+	fnum1 = (uint16_t)-1;
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("close - 2 failed (%s)\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	if (expect_rename_success) {
+		status = cli_getatr(cli1, indir1, NULL, &fsize, NULL);
+		if (!NT_STATUS_IS_OK(status)) {
+			printf("getatr - 2 - replaced - failed (%s)\n",
+			       nt_errstr(status));
+			correct = false;
+			goto out;
+		}
+		if (fsize != 0) {
+			printf("getatr - 2 - replaced - incorrect file size\n");
+			correct = false;
+			goto out;
+		}
+	}
+
+	cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, indir1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_rmdir(cli1, dname);
+
+	/*
+	 * rename and replace using FILE_RENAME_INFORMATION, same
+	 * directories.
+	 */
+	status = cli_mkdir(cli1, dname);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("3rd test mkdir failed - %s\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	/* set up a file whose length is 10 bytes - this will be
+	 * replaced by a zero-length file
+	 */
+	status = cli_ntcreate(cli1, indir1, 0, GENERIC_WRITE_ACCESS,
+			      FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+			      FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("3rd create to-replace file failed - %s\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	status = cli_writeall(cli1, fnum1, 0, buf, 0, sizeof(buf), NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("write - 3 - to-replace- failed (%s)\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	status = cli_close(cli1, fnum1);
+	fnum1 = (uint16_t)-1;
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("close - 3 - to-replace- failed (%s)\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	status = cli_getatr(cli1, indir1, NULL, &fsize, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("getatr - 3 - to-replace- failed (%s)\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	if ((size_t)fsize != sizeof(buf)) {
+		printf("getatr - 3 - to-replace- incorrect file size\n");
+		correct = false;
+		goto out;
+	}
+
+	status = cli_ntcreate(cli1, indir, 0, GENERIC_READ_ACCESS,
+			      FILE_ATTRIBUTE_NORMAL,
+			      FILE_SHARE_DELETE | FILE_SHARE_READ,
+			      FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("3rd open failed - %s\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+
+	/* The on-the-wire rename destination is relative to
+	 * share root in SMB2+ and relative to source
+	 * in NT1 dialect
+	 */
+	rename_dest = indir1;
+	if (!is_smb2) {
+		rename_dest = fname1;
+	}
+
+	status = do_rename(cli1, indir, rename_dest, true);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("3rd rename failed - %s\n", nt_errstr(status));
+		correct = false;
+		goto out;
+	} else {
+		printf("3rd rename succeeded (this is correct)\n");
+	}
+
+	status = cli_close(cli1, fnum1);
+	fnum1 = (uint16_t)-1;
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("close - 3 failed (%s)\n", nt_errstr(status));
+		goto out;
+	}
+
+	status = cli_getatr(cli1, indir1, NULL, &fsize, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("getatr - 3 - replaced - failed (%s)\n",
+		       nt_errstr(status));
+		correct = false;
+		goto out;
+	}
+	if (fsize != 0) {
+		printf("getatr - 3 - replaced - incorrect file size\n");
+		correct = false;
+		goto out;
+	}
+
+	cli_unlink(cli1, indir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, indir1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_rmdir(cli1, dname);
+
+out:
+	if (fnum1 != (uint16_t)-1) {
+		cli_close(cli1, fnum1);
+	}
+
+	cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, indir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_unlink(cli1, indir1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	cli_rmdir(cli1, dname);
+	cli_rmdir(cli1, dname1);
+
+	if (!torture_close_connection(cli1)) {
+		correct = false;
+	}
+
+	return correct;
+}
+
+/*
   Test owner rights ACE.
  */
 static bool run_owner_rights(int dummy)
@@ -11494,6 +11886,7 @@ static struct {
 	{"XCOPY", run_xcopy, 0},
 	{"RENAME", run_rename, 0},
 	{"RENAME-ACCESS", run_rename_access, 0},
+	{"RENAME-REPLACE", run_rename_replace, 0},
 	{"OWNER-RIGHTS", run_owner_rights, 0},
 	{"DELETE", run_deletetest, 0},
 	{"WILDDELETE", run_wild_deletetest, 0},
-- 
2.9.5


From f3ba35ca7e2dfac12996b8516ce24828bbfa56ee Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at vfunction.com>
Date: Wed, 18 Oct 2017 19:04:37 +0300
Subject: [PATCH 3/3] selftest: use RENAME-REPLACE torture test

Run RENAME-REPLACE torture test in the default test suite
protocol dialect.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/selftest/tests.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index c1e08d5..966a8d9 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -78,7 +78,8 @@ tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7"
         "CLEANUP1",
         "CLEANUP2",
         "CLEANUP4",
-        "BAD-NBT-SESSION"]
+        "BAD-NBT-SESSION",
+        "RENAME-REPLACE"]
 
 for t in 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/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
-- 
2.9.5



More information about the cifs-protocol mailing list