[PATCH] Fix for bug #9706 - Parameter is incorrect on Android

Jeremy Allison jra at samba.org
Fri Mar 15 15:56:00 MDT 2013


On Fri, Mar 15, 2013 at 11:40:21AM -0700, Jeremy Allison wrote:
> 
> Ok, I've done the tests. Looks like the correct response
> is to return shorter reads than what the client asks if
> the reads are out of range. The only case where we should
> still fail is when the read request out of range and is
> done in an andX chain, so I've left that code check in
> place.
> 
> I have a modified server patch that does this. It'll make
> Andrew happy as we no longer need to look at RA_SAMBA, as
> we just cope in the same way as Windows does with whatever
> the client asks for. All we do is modify max_pdu to cope
> with what the client told us it can cope with. Client tests
> also expanded to cope with signed+sealed requests as well
> as the new read values.
> 
> I'll post on the bug and a new patchset here shortly.

And here is the fixed patchset. It applies cleanly
to master.. I'll also upload a 4.0.next version
to the bug report.

Please test and push if you're happy with it.

Jeremy.
-------------- next part --------------
From a490a85376da04f73f50e036a6d1d3a969ac0367 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 13 Mar 2013 14:56:06 -0700
Subject: [PATCH 01/10] Ensure we send CAP_LARGE_READX/CAP_LARGE_WRITEX to the
 server on SMB1 sessionsetupX.

A Windows client doesn't do this, but that's because they never do large
reads/writes over SMB1. It's in the spec that this should occur, and
Samba 3.6.x uses it. Also, MacOSX, CIFSFS and Android (jCIFS) honour
this setting and send it. We need to as well in order to give servers
a better idea of our capabilities.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/smb/smb_constants.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h
index f1ecbe9..c447795 100644
--- a/libcli/smb/smb_constants.h
+++ b/libcli/smb/smb_constants.h
@@ -234,6 +234,8 @@ enum smb_signing_setting {
 	CAP_NT_SMBS | \
 	CAP_STATUS32 | \
 	CAP_LEVEL_II_OPLOCKS | \
+	CAP_LARGE_READX | \
+	CAP_LARGE_WRITEX | \
 	CAP_EXTENDED_SECURITY | \
 	0)
 #define SMB_CAP_SERVER_MASK ( \
@@ -245,8 +247,6 @@ enum smb_signing_setting {
 	CAP_NT_FIND | \
 	CAP_DFS | \
 	CAP_W2K_SMBS | \
-	CAP_LARGE_READX | \
-	CAP_LARGE_WRITEX | \
 	CAP_LWIO | \
 	CAP_UNIX | \
 	0)
-- 
1.8.1.3


From e40984781f28ff25a7f7aec0d00fbf6fdb7e5cbb Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 13 Mar 2013 15:23:52 -0700
Subject: [PATCH 02/10] smb1cli_inbuf_parse_chain() and
 smb1cli_conn_dispatch_incoming() should use smb_len_tcp.

They have to cope with large READX call replies that have
a length greater than smb_len_nbt() can handle.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/smb/smbXcli_base.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 4c60a05..b8cd7df 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -1618,7 +1618,7 @@ static NTSTATUS smb1cli_inbuf_parse_chain(uint8_t *buf, TALLOC_CTX *mem_ctx,
 	NTSTATUS status;
 	size_t min_size = MIN_SMB_SIZE;
 
-	buflen = smb_len_nbt(buf);
+	buflen = smb_len_tcp(buf);
 	taken = 0;
 
 	hdr = buf + NBT_HDR_SIZE;
@@ -1845,7 +1845,7 @@ static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
 	uint16_t mid;
 	bool oplock_break;
 	uint8_t *inhdr = inbuf + NBT_HDR_SIZE;
-	size_t len = smb_len_nbt(inbuf);
+	size_t len = smb_len_tcp(inbuf);
 	struct iovec *iov = NULL;
 	int num_iov = 0;
 	struct tevent_req **chain = NULL;
-- 
1.8.1.3


From 8796fa108100942089b5d29a3a856e69e2993248 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 15 Mar 2013 11:53:04 -0700
Subject: [PATCH 03/10] Remove server_will_accept_large_read() and erroneous
 comment.

We're going to replace this with a function that calculates
the max PDU to return on a read and supports short reads.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/reply.c | 29 +----------------------------
 1 file changed, 1 insertion(+), 28 deletions(-)

diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 64c4fdb..b684c26 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3849,26 +3849,6 @@ nosendfile_read:
 }
 
 /****************************************************************************
- MacOSX clients send large reads without telling us they are going to do that.
- Bug #9572 - File corruption during SMB1 read by Mac OSX 10.8.2 clients
- Allow this if we are talking to a Samba client, or if we told the client
- we supported this.
-****************************************************************************/
-
-static bool server_will_accept_large_read(void)
-{
-	/* Samba client ? No problem. */
-	if (get_remote_arch() == RA_SAMBA) {
-		return true;
-	}
-	/* Need UNIX extensions. */
-	if (!lp_unix_extensions()) {
-		return false;
-	}
-	return true;
-}
-
-/****************************************************************************
  Reply to a read and X.
 ****************************************************************************/
 
@@ -3914,14 +3894,7 @@ void reply_read_and_X(struct smb_request *req)
 	}
 
 	upper_size = SVAL(req->vwv+7, 0);
-	if ((upper_size != 0) && server_will_accept_large_read()) {
-		/*
-		 * This is Samba only behavior (up to Samba 3.6)!
-		 *
-		 * Windows 2008 R2 ignores the upper_size,
-		 * so we do unless unix extentions are active
-		 * or "smbclient" is talking to us.
-		 */
+	if (upper_size != 0) {
 		smb_maxcnt |= (upper_size<<16);
 		if (upper_size > 1) {
 			/* Can't do this on a chained packet. */
-- 
1.8.1.3


From 094b76bc108da4cd001022d16cf2558fab208ea8 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 15 Mar 2013 11:57:48 -0700
Subject: [PATCH 04/10] Add functions calc_max_read_pdu()/calc_read_size() to
 work out the length we should return.

LARGE_READX test shows it's always safe to return a short read.
Windows does so. Do the calculations to return what will fit
in a read depending on what the client negotiated.

Conservative, in that if no flags are negotiated then the
max read is set to default Win2K12 max_pdu size of 0x10000 + headers.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/reply.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index b684c26..94cc194 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3849,6 +3849,80 @@ nosendfile_read:
 }
 
 /****************************************************************************
+ Work out how much space we have for a read return.
+****************************************************************************/
+
+static size_t calc_max_read_pdu(const struct smb_request *req)
+{
+	/* Default Win2K12 max_pdu size of 0x10000 + headers. */
+	size_t max_pdu = 0x10000 + (smb_size -4 + 12*2);
+
+	if (req->encrypted) {
+		/*
+		 * Don't take encrypted traffic up to the
+		 * limit. There are padding considerations
+		 * that make that tricky.
+		 */
+		return max_pdu;
+	}
+
+	if (req->sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) {
+		if (srv_is_signing_active(req->sconn)) {
+			/*
+			 * Ignore POSIX large read size on a signed
+			 * connection.
+			 */
+			if (global_client_caps & CAP_LARGE_READX) {
+				max_pdu = 0x1FFFF;
+			}
+		} else {
+			/*
+			 * We can do ultra-large POSIX reads.
+			 */
+			max_pdu = 0xFFFFFF;
+		}
+	} else if (global_client_caps & CAP_LARGE_READX) {
+		/*
+		 * "Normal" max PDU size.
+		 */
+		max_pdu = 0x1FFFF;
+	}
+
+	return max_pdu;
+}
+
+/****************************************************************************
+ Calculate how big a read can be. Copes with all clients. It's always
+ safe to return a short read - Windows does this.
+****************************************************************************/
+
+static size_t calc_read_size(const struct smb_request *req,
+				size_t upper_size,
+				size_t lower_size)
+{
+	size_t max_pdu = calc_max_read_pdu(req);
+	size_t total_size = 0;
+
+	/*
+	 * Windows explicitly ignores upper size of 0xFFFF.
+	 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
+	 * We must do the same as these will never fit even in
+	 * an extended size NetBIOS packet.
+	 */
+	if (upper_size == 0xFFFF) {
+		upper_size = 0;
+	}
+
+	total_size = ((upper_size<<16) | lower_size);
+
+	/*
+	 * LARGE_READX test shows it's always safe to return
+	 * a short read. Windows does so.
+	 */
+	return MIN(total_size, max_pdu - (smb_size -4 + 12*2));
+}
+
+/****************************************************************************
  Reply to a read and X.
 ****************************************************************************/
 
@@ -3895,7 +3969,7 @@ void reply_read_and_X(struct smb_request *req)
 
 	upper_size = SVAL(req->vwv+7, 0);
 	if (upper_size != 0) {
-		smb_maxcnt |= (upper_size<<16);
+		smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
 		if (upper_size > 1) {
 			/* Can't do this on a chained packet. */
 			if ((CVAL(req->vwv+0, 0) != 0xFF)) {
-- 
1.8.1.3


From 19d23a71b3db9a999cb0015f7b6e16c749576915 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 15 Mar 2013 12:02:28 -0700
Subject: [PATCH 05/10] Don't just check for upper_size > 1, check for actual
 PDU space.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/reply.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 94cc194..caaeb83 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3970,7 +3970,7 @@ void reply_read_and_X(struct smb_request *req)
 	upper_size = SVAL(req->vwv+7, 0);
 	if (upper_size != 0) {
 		smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
-		if (upper_size > 1) {
+		if (smb_maxcnt > (0x1FFFF - (smb_size -4 + 12*2)))  {
 			/* Can't do this on a chained packet. */
 			if ((CVAL(req->vwv+0, 0) != 0xFF)) {
 				reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
-- 
1.8.1.3


From 2dd51b32cab9d9242e767eff5695782e6cc14c76 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 15 Mar 2013 12:03:47 -0700
Subject: [PATCH 06/10] Remove unneeded checks. We truncate the read inside
 calc_read_size() now.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/reply.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index caaeb83..e35d043 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3977,20 +3977,6 @@ void reply_read_and_X(struct smb_request *req)
 				END_PROFILE(SMBreadX);
 				return;
 			}
-			/* We currently don't do this on signed or sealed data. */
-			if (srv_is_signing_active(req->sconn) ||
-			    is_encrypted_packet(req->sconn, req->inbuf)) {
-				reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
-				END_PROFILE(SMBreadX);
-				return;
-			}
-			/* Is there room in the reply for this data ? */
-			if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
-				reply_nterror(req,
-					      NT_STATUS_INVALID_PARAMETER);
-				END_PROFILE(SMBreadX);
-				return;
-			}
 			big_readX = True;
 		}
 	}
-- 
1.8.1.3


From 226c248c0efa67d3023bff295e4eead2f9ce4a68 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 13 Mar 2013 15:41:05 -0700
Subject: [PATCH 07/10] Add set_XX() functions for fields we need to modify for
 testing large READX.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/smb/smbXcli_base.c | 10 ++++++++++
 libcli/smb/smbXcli_base.h |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index b8cd7df..571ef28 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -585,11 +585,21 @@ uint32_t smb1cli_conn_capabilities(struct smbXcli_conn *conn)
 	return conn->smb1.capabilities;
 }
 
+void smb1cli_conn_set_capabilities(struct smbXcli_conn *conn, uint32_t capabilities)
+{
+	conn->smb1.capabilities = capabilities;
+}
+
 uint32_t smb1cli_conn_max_xmit(struct smbXcli_conn *conn)
 {
 	return conn->smb1.max_xmit;
 }
 
+void smb1cli_conn_set_max_xmit(struct smbXcli_conn *conn, uint32_t max_xmit)
+{
+	conn->smb1.max_xmit = max_xmit;
+}
+
 uint32_t smb1cli_conn_server_session_key(struct smbXcli_conn *conn)
 {
 	return conn->smb1.server.session_key;
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index f7b60d3..476f68d 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -67,7 +67,9 @@ void smbXcli_req_unset_pending(struct tevent_req *req);
 bool smbXcli_req_set_pending(struct tevent_req *req);
 
 uint32_t smb1cli_conn_capabilities(struct smbXcli_conn *conn);
+void smb1cli_conn_set_capabilities(struct smbXcli_conn *conn, uint32_t capabilities);
 uint32_t smb1cli_conn_max_xmit(struct smbXcli_conn *conn);
+void smb1cli_conn_set_max_xmit(struct smbXcli_conn *conn, uint32_t max_xmit);
 uint32_t smb1cli_conn_server_session_key(struct smbXcli_conn *conn);
 const uint8_t *smb1cli_conn_server_challenge(struct smbXcli_conn *conn);
 uint16_t smb1cli_conn_server_security_mode(struct smbXcli_conn *conn);
-- 
1.8.1.3


From 69c288d13e76c7196c8c58dd375b2e1d6345f5fc Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 13 Mar 2013 15:43:21 -0700
Subject: [PATCH 08/10] Add new LARGE_READX test to investigate large SMBreadX
 behavior.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/torture/torture.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 308 insertions(+)

diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 93b9cfd..cbc431b 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -7239,6 +7239,313 @@ static bool run_windows_write(int dummy)
 	return ret;
 }
 
+static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
+{
+	size_t max_pdu = cli->server_posix_capabilities ? 0xFFFFFF : 0x1FFFF;
+
+	if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
+		len_requested &= 0xFFFF;
+	}
+
+	if (smb1cli_conn_encryption_on(cli->conn)) {
+		return MIN(len_requested, 0x10000 + (smb_size -4 + 12*2));
+	} else if (smb1cli_conn_signing_is_active(cli->conn)) {
+		/*
+		 * When signed or encrypted we don't return PDU's
+		 * larger than normal NetBIOS 0x1FFFF PDU size.
+		 */
+		return MIN(len_requested, 0x1FFFF - (smb_size -4 + 12*2));
+	}
+
+	/* Max size depends on whether POSIX was negotiated. */
+	return MIN(len_requested, max_pdu - (smb_size -4 + 12*2));
+}
+
+static bool check_read_call(struct cli_state *cli,
+				uint16_t fnum,
+				uint8_t *buf,
+				size_t len_requested)
+{
+	NTSTATUS status;
+	struct tevent_req *req = NULL;
+	ssize_t len_read = 0;
+	size_t len_expected = 0;
+	struct tevent_context *ev = NULL;
+
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		return false;
+	}
+
+	req = cli_read_andx_send(talloc_tos(),
+				ev,
+				cli,
+				fnum,
+				0,
+				len_requested);
+
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		return false;
+	}
+
+	status = cli_read_andx_recv(req, &len_read, &buf);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
+		return false;
+	}
+
+	TALLOC_FREE(req);
+	TALLOC_FREE(ev);
+
+	len_expected = calc_expected_return(cli, len_requested);
+
+	if (len_expected > 0x10000 && len_read == 0x10000) {
+		/* Windows servers only return a max of 0x10000,
+		   doesn't matter if you set CAP_LARGE_READX in
+		   the client sessionsetupX call or not. */
+		d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
+			(unsigned int)len_requested);
+	} else if (len_read != len_expected) {
+		d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
+			(unsigned int)len_requested,
+			(unsigned int)len_read,
+			(unsigned int)len_expected);
+		return false;
+	} else {
+		d_printf("Correct read reply.\n");
+	}
+
+	return true;
+}
+
+/* Test large readX variants. */
+static bool large_readx_tests(struct cli_state *cli,
+				uint16_t fnum,
+				uint8_t *buf)
+{
+	/* A read of 0xFFFF0001 should *always* return 1 byte. */
+	if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
+		return false;
+	}
+	/* A read of 0x10000 should return 10000 bytes. */
+	if (check_read_call(cli, fnum, buf,    0x10000) == false) {
+		return false;
+	}
+	/* A read of 0x1FFFF - (smb_size -4 + 12*2) should return
+	   the requested number of bytes. */
+	if (check_read_call(cli, fnum, buf, 0x1FFFF - (smb_size -4 + 12*2)) == false) {
+		return false;
+	}
+	/* A read of 1MB should return 1MB bytes (on Samba). */
+	if (check_read_call(cli, fnum, buf,   0x100000) == false) {
+		return false;
+	}
+
+	if (check_read_call(cli, fnum, buf,    0x20001) == false) {
+		return false;
+	}
+	if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
+		return false;
+	}
+	if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
+		return false;
+	}
+	return true;
+}
+
+static bool run_large_readx(int dummy)
+{
+	uint8_t *buf = NULL;
+	struct cli_state *cli = NULL;
+	bool correct = false;
+	const char *fname = "\\large_readx.dat";
+	NTSTATUS status;
+	uint16_t fnum = -1;
+	uint32_t normal_caps = 0;
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	printf("starting large_readx test\n");
+
+	if (!torture_open_connection(&cli, 0)) {
+		goto out;
+	}
+
+	normal_caps = smb1cli_conn_capabilities(cli->conn);
+
+	if (!(normal_caps & CAP_LARGE_READX)) {
+		d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
+			(unsigned int)normal_caps);
+		goto out;
+	}
+
+	cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+	/* Create a file of size 4MB. */
+	status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS,
+			FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
+			0, 0, &fnum);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("open %s failed: %s\n", fname, nt_errstr(status));
+		goto out;
+	}
+
+	/* Write 4MB. */
+	buf = talloc_zero_array(frame, uint8_t, 4*1024*1024);
+	if (buf == NULL) {
+		goto out;
+	}
+
+	status = cli_writeall(cli,
+				fnum,
+				0,
+				buf,
+				0,
+				4*1024*1024,
+				NULL);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("cli_writeall failed: %s\n", nt_errstr(status));
+		goto out;
+	}
+
+	/*
+	 * Mangle the cli state to allow us to do a read
+	 * with upper bytes of 0xFFFF.
+	 */
+	cli->server_posix_capabilities &= ~CIFS_UNIX_LARGE_READ_CAP;
+	smb1cli_conn_set_max_xmit(cli->conn, 0xFFFFFF00);
+	smb1cli_conn_set_capabilities(cli->conn, (normal_caps & ~CAP_LARGE_READX));
+
+	if (!large_readx_tests(cli, fnum, buf)) {
+		goto out;
+	}
+
+	status = cli_close(cli, fnum);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("cli_close failed: %s\n", nt_errstr(status));
+		goto out;
+	}
+
+	fnum = -1;
+
+	if (!torture_close_connection(cli)) {
+		goto out;
+	}
+
+	cli = NULL;
+
+	/*
+	 * Open a second connection ensuring we don't
+	 * announce ourselves as Samba. This way we
+	 * should elicit the same behavior from a
+	 * Samba server as we give to a Windows
+	 * or MacOSX client.
+	 */
+
+	if (!(cli = open_nbt_connection())) {
+		goto out;
+	}
+
+	/* Ensure we don't announce ourselves as Samba. */
+	status = smbXcli_negprot(cli->conn,
+				cli->timeout,
+				PROTOCOL_NT1,
+				PROTOCOL_NT1);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+
+	status = cli_session_setup(cli,
+				username,
+				password,
+				strlen(password)+1,
+				password,
+				strlen(password)+1,
+				workgroup);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+
+	status = cli_tree_connect(cli,
+				share,
+				"?????",
+				password,
+				strlen(password)+1);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto out;
+	}
+
+	cli_set_timeout(cli, 120000); /* set a really long timeout (2 minutes) */
+
+	if (do_encrypt) {
+		if (force_cli_encryption(cli, share) == false) {
+			goto out;
+		}
+	}
+
+	normal_caps = smb1cli_conn_capabilities(cli->conn);
+
+	if (!(normal_caps & CAP_LARGE_READX)) {
+		d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
+			(unsigned int)normal_caps);
+		goto out;
+	}
+
+	status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
+			FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
+			0, 0, &fnum);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
+		goto out;
+	}
+
+	/*
+	 * Mangle the cli state to allow us to do a read
+	 * with upper bytes of 0xFFFF.
+	 */
+	cli->server_posix_capabilities &= ~CIFS_UNIX_LARGE_READ_CAP;
+	smb1cli_conn_set_max_xmit(cli->conn, 0xFFFFFF00);
+	smb1cli_conn_set_capabilities(cli->conn, (normal_caps & ~CAP_LARGE_READX));
+
+	if (!large_readx_tests(cli, fnum, buf)) {
+		goto out;
+	}
+
+	correct = true;
+	printf("Success on large_readx test\n");
+
+  out:
+
+	if (fnum != -1) {
+		status = cli_close(cli, fnum);
+		if (!NT_STATUS_IS_OK(status)) {
+			d_printf("cli_close failed: %s\n", nt_errstr(status));
+		}
+		fnum = -1;
+	}
+
+	status = cli_unlink(cli,
+				fname,
+				FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("unlink failed (%s)\n", nt_errstr(status));
+	}
+
+	if (cli) {
+		if (!torture_close_connection(cli)) {
+			correct = false;
+		}
+	}
+
+	TALLOC_FREE(frame);
+
+	printf("finished large_readx test\n");
+	return correct;
+}
+
+
 static bool run_cli_echo(int dummy)
 {
 	struct cli_state *cli;
@@ -9153,6 +9460,7 @@ static struct {
 	{ "CHAIN2", run_chain2, 0},
 	{ "CHAIN3", run_chain3, 0},
 	{ "WINDOWS-WRITE", run_windows_write, 0},
+	{ "LARGE_READX", run_large_readx, 0},
 	{ "NTTRANS-CREATE", run_nttrans_create, 0},
 	{ "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
 	{ "CLI_ECHO", run_cli_echo, 0},
-- 
1.8.1.3


From 55173e0b606d54d5c334127385cd915087a25d51 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 13 Mar 2013 15:44:22 -0700
Subject: [PATCH 09/10] New LARGE_READX doesn't work against ntvfs server.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 selftest/knownfail | 1 +
 1 file changed, 1 insertion(+)

diff --git a/selftest/knownfail b/selftest/knownfail
index 180a543..cdd7227 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -13,6 +13,7 @@
 ^samba3.smbtorture_s3.plain\(dc\).DIR-CREATETIME # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(dc\).DELETE-LN # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(dc\).POSIX # Fails against the s4 ntvfs server
+^samba3.smbtorture_s3.plain\(dc\).LARGE_READX # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(dc\).UID-REGRESSION-TEST # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(dc\).SHORTNAME-TEST # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(dc\).POSIX-APPEND # Fails against the s4 ntvfs server
-- 
1.8.1.3


From e2e143f886cb872cc335180e4b41c629dc9a14c9 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 13 Mar 2013 15:45:12 -0700
Subject: [PATCH 10/10] Add LARGE_READX test into our make test infrastructure.

Tested against non-encrypted and encrypted connections.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/selftest/tests.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 30253ca..1c123f5 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -54,7 +54,7 @@ plantestsuite("samba3.blackbox.registry.upgrade", "s3dc:local", [os.path.join(sa
 tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7", "LOCK9",
         "UNLINK", "BROWSE", "ATTR", "TRANS2", "TORTURE",
         "OPLOCK1", "OPLOCK2", "OPLOCK4", "STREAMERROR",
-        "DIR", "DIR1", "DIR-CREATETIME", "TCON", "TCONDEV", "RW1", "RW2", "RW3", "RW-SIGNING",
+        "DIR", "DIR1", "DIR-CREATETIME", "TCON", "TCONDEV", "RW1", "RW2", "RW3", "LARGE_READX", "RW-SIGNING",
         "OPEN", "XCOPY", "RENAME", "DELETE", "DELETE-LN", "PROPERTIES", "W2K",
         "TCON2", "IOCTL", "CHKPATH", "FDSESS", "CHAIN1", "CHAIN2",
         "CHAIN3",
-- 
1.8.1.3



More information about the samba-technical mailing list