[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Wed Mar 20 14:54:02 MDT 2013


The branch, master has been updated
       via  599a699 s4:torture: let raw.read accept larger reads than 0x10000
       via  c9066b0 s4:torture: raw.read fix large reads against windows
       via  df618e3 s3:selftest: Add LARGE_READX test into our make test infrastructure.
       via  d9afb2b s3:torture: Add new LARGE_READX test to investigate large SMBreadX behavior.
       via  5a05e68 s4:smb_server: fix large read_andx requests
       via  fd88520 s3:smbd: Add functions calc_max_read_pdu()/calc_read_size() to work out the length we should return.
       via  21707de s3:smbd: Remove server_will_accept_large_read() and erroneous comment.
       via  36f6a8a s3:smbd: Fix off-by 4 error in wrap protection code in create_outbuf()
       via  b80111a s3:smbd: add some const to req_is_in_chain()
       via  be98c1c s3:smbd: remove silly (SMB_OFF_T_BITS == 64) checks
       via  d24b8af s3:smbd: keep global_client_caps and max_send from the first successful session setup
       via  40c3db9 s3:libsmb: let cli_read_andx_create() accept any length
       via  1111d46 libcli/smb: smb1cli_inbuf_parse_chain() and smb1cli_conn_dispatch_incoming() should use smb_len_tcp.
       via  53d348d libcli/smb: defer failing for missing NEGOTIATE_SECURITY_SIGNATURES_ENABLED
       via  b041dc9 s3:libsmb: make use of SMB_CAP_LEGACY_CLIENT_MASK instead of SMB_CAP_CLIENT_MASK
       via  3d7a4db libcli/smb: add SMB_CAP_LEGACY_CLIENT_MASK define
      from  f7564ca s3:registry accept windows like long hivenames

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 599a699adec1f8f0a432d9c34f378d48930ca29b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 20 08:49:20 2013 +0100

    s4:torture: let raw.read accept larger reads than 0x10000
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Wed Mar 20 21:53:20 CET 2013 on sn-devel-104

commit c9066b057a6aa3cc1960124c9f2519413a2b57da
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 19 17:11:03 2013 +0100

    s4:torture: raw.read fix large reads against windows
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit df618e33ac011c018374af8da021c7b5f1cc1427
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Mar 13 15:45:12 2013 -0700

    s3:selftest: 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>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit d9afb2b14df642de5d9225d10cc20cac7fd5133f
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Mar 13 15:43:21 2013 -0700

    s3:torture: Add new LARGE_READX test to investigate large SMBreadX behavior.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 5a05e687ce724ea808cdb1e6627b9c67804eb879
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Mar 18 19:50:38 2013 +0100

    s4:smb_server: fix large read_andx requests
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit fd88520497b4043e9d81656f7cb56a7b25245c2a
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Mar 15 11:57:48 2013 -0700

    s3:smbd: 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.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 21707defe06e1db18a6645b0b56db4178e3df5f6
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Mar 15 11:53:04 2013 -0700

    s3:smbd: 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>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 36f6a8abb2ad0c7d0551679cc61a29fa2dc16d80
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Mar 18 15:05:24 2013 -0700

    s3:smbd: Fix off-by 4 error in wrap protection code in create_outbuf()
    
    Subtract 4 from smb_size (39) here as the length
    of the SMB reply following the 4 byte type+length
    field can be up to 0xFFFFFF bytes.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit b80111adb3a30ff386b3c45fcf962c417256bb59
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Mar 18 12:36:30 2013 +0100

    s3:smbd: add some const to req_is_in_chain()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit be98c1c889166a5f2b83e1e29d7dcbbaf6baab8f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 19 13:24:46 2013 +0100

    s3:smbd: remove silly (SMB_OFF_T_BITS == 64) checks
    
    configure will abort if sizeof(off_t) is not 8.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit d24b8afb79f75b1db9301b79862be484a4932979
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Mar 18 10:10:25 2013 +0100

    s3:smbd: keep global_client_caps and max_send from the first successful session setup
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 40c3db9b6a584a6c243fd02b12269d54e7425fea
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Mar 18 09:33:00 2013 +0100

    s3:libsmb: let cli_read_andx_create() accept any length
    
    It's up to the server to decide the allowed length.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1111d46cc52e868cf4894909b71f1574196e2887
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Mar 13 15:23:52 2013 -0700

    libcli/smb: 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>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 53d348dff082f9c18e06f99ec646127467f339e7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Mar 18 15:02:55 2013 +0100

    libcli/smb: defer failing for missing NEGOTIATE_SECURITY_SIGNATURES_ENABLED
    
    Windows servers take a look at the FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
    flag during a session setup and turn on signing if the client requires it.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit b041dc9451e210acc82a82b75e02e4166d8973d5
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 19 09:03:38 2013 +0100

    s3:libsmb: make use of SMB_CAP_LEGACY_CLIENT_MASK instead of SMB_CAP_CLIENT_MASK
    
    This should allow smbclient to keep using large reads against older Samba versions
    (<= 3.6.x) and other servers that may also require this.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 3d7a4db6bc5cd42432393bf69622c435e67e811f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 19 09:02:52 2013 +0100

    libcli/smb: add SMB_CAP_LEGACY_CLIENT_MASK define
    
    Older Samba releases (<= 3.6.x)
    expect the client to send CAP_LARGE_READX
    in order to let the client use large reads.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 libcli/smb/smbXcli_base.c      |   13 ++-
 libcli/smb/smb_constants.h     |   10 ++
 source3/libsmb/cliconnect.c    |    8 +-
 source3/libsmb/clireadwrite.c  |    7 -
 source3/selftest/tests.py      |    2 +-
 source3/smbd/negprot.c         |    5 +-
 source3/smbd/process.c         |   19 ++-
 source3/smbd/proto.h           |    2 +-
 source3/smbd/reply.c           |  116 +++++++++-----
 source3/smbd/sesssetup.c       |   14 ++-
 source3/torture/torture.c      |  338 +++++++++++++++++++++++++++++++++++++++-
 source4/smb_server/smb/reply.c |   18 ++-
 source4/torture/raw/read.c     |   18 +--
 13 files changed, 482 insertions(+), 88 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 4c60a05..5a5828a 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;
@@ -4046,6 +4046,15 @@ static void smbXcli_negprot_smb1_done(struct tevent_req *subreq)
 		if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
 			server_signing = "supported";
 			server_allowed = true;
+		} else if (conn->mandatory_signing) {
+			/*
+			 * We have mandatory signing as client
+			 * lets assume the server will look at our
+			 * FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
+			 * flag in the session setup
+			 */
+			server_signing = "not announced";
+			server_allowed = true;
 		}
 		if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
 			server_signing = "required";
diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h
index f1ecbe9..6dd7b28 100644
--- a/libcli/smb/smb_constants.h
+++ b/libcli/smb/smb_constants.h
@@ -253,6 +253,16 @@ enum smb_signing_setting {
 #define SMB_CAP_CLIENT_MASK ( \
 	CAP_DYNAMIC_REAUTH | \
 	0)
+/*
+ * Older Samba releases (<= 3.6.x)
+ * expect the client to send CAP_LARGE_READX
+ * in order to let the client use large reads.
+ */
+#define SMB_CAP_LEGACY_CLIENT_MASK ( \
+	SMB_CAP_CLIENT_MASK | \
+	CAP_LARGE_READX | \
+	CAP_LARGE_WRITEX | \
+	0)
 
 /* Client-side offline caching policy types */
 enum csc_policy {
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 52d8e0c..872900c 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -341,9 +341,13 @@ static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
 	 * - client only flags
 	 * - flags used in both directions
 	 *
-	 * We do not echo the server only flags.
+	 * We do not echo the server only flags, except some legacy flags.
+	 *
+	 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
+	 * CAP_LARGE_WRITEX in order to allow us to do large reads
+	 * against old Samba releases (<= 3.6.x).
 	 */
-	client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_CLIENT_MASK);
+	client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
 
 	/*
 	 * Session Setup specific flags CAP_DYNAMIC_REAUTH
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 75c1683..47e7f1b 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -132,13 +132,6 @@ struct tevent_req *cli_read_andx_create(TALLOC_CTX *mem_ctx,
 	struct cli_read_andx_state *state;
 	uint8_t wct = 10;
 
-	if (size > cli_read_max_bufsize(cli)) {
-		DEBUG(0, ("cli_read_andx_send got size=%d, can only handle "
-			  "size=%d\n", (int)size,
-			  (int)cli_read_max_bufsize(cli)));
-		return NULL;
-	}
-
 	req = tevent_req_create(mem_ctx, &state, struct cli_read_andx_state);
 	if (req == NULL) {
 		return NULL;
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",
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index e33350c..cfe0983 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -284,11 +284,10 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
 		capabilities |= CAP_UNIX;
 	}
 
-	if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
+	if (lp_large_readwrite())
 		capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
 
-	if (SMB_OFF_T_BITS == 64)
-		capabilities |= CAP_LARGE_FILES;
+	capabilities |= CAP_LARGE_FILES;
 
 	if (lp_readraw() && lp_writeraw())
 		capabilities |= CAP_RAW_MODE;
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 1640cca..1ebda79 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1270,11 +1270,13 @@ static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
 			  const char *inbuf, char **outbuf, uint8_t num_words,
 			  uint32_t num_bytes)
 {
+	size_t smb_len = MIN_SMB_SIZE + VWV(num_words) + num_bytes;
+
 	/*
-         * Protect against integer wrap
-         */
-	if ((num_bytes > 0xffffff)
-	    || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
+	 * Protect against integer wrap.
+	 * The SMB layer reply can be up to 0xFFFFFF bytes.
+	 */
+	if ((num_bytes > 0xffffff) || (smb_len > 0xffffff)) {
 		char *msg;
 		if (asprintf(&msg, "num_bytes too large: %u",
 			     (unsigned)num_bytes) == -1) {
@@ -1283,8 +1285,11 @@ static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
 		smb_panic(msg);
 	}
 
+	/*
+	 * Here we include the NBT header for now.
+	 */
 	*outbuf = talloc_array(mem_ctx, char,
-			       smb_size + num_words*2 + num_bytes);
+			       NBT_HDR_SIZE + smb_len);
 	if (*outbuf == NULL) {
 		return false;
 	}
@@ -1296,7 +1301,7 @@ static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
 	 * himself
 	 */
 	if (num_words != 0) {
-		memset(*outbuf + smb_vwv0, 0, num_words*2);
+		memset(*outbuf + (NBT_HDR_SIZE + HDR_VWV), 0, VWV(num_words));
 	}
 
 	return true;
@@ -3631,7 +3636,7 @@ void smbd_process(struct tevent_context *ev_ctx,
 	exit_server_cleanly(NULL);
 }
 
-bool req_is_in_chain(struct smb_request *req)
+bool req_is_in_chain(const struct smb_request *req)
 {
 	if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
 		/*
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index bd22dd3..7e13049 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -801,7 +801,7 @@ bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
 		      struct smbd_server_connection *sconn,
 		      bool encrypted, uint32_t seqnum,
 		      struct smb_request ***reqs, unsigned *num_reqs);
-bool req_is_in_chain(struct smb_request *req);
+bool req_is_in_chain(const struct smb_request *req);
 void smbd_process(struct tevent_context *ev_ctx,
 		  struct messaging_context *msg_ctx,
 		  int sock_fd,
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 2c31f15..8b500c5 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3848,23 +3848,81 @@ 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.
+ Work out how much space we have for a read return.
 ****************************************************************************/
 
-static bool server_will_accept_large_read(void)
+static size_t calc_max_read_pdu(const struct smb_request *req)
 {
-	/* Samba client ? No problem. */
-	if (get_remote_arch() == RA_SAMBA) {
-		return true;
+	if (req->sconn->conn->protocol < PROTOCOL_NT1) {
+		return req->sconn->smb1.sessions.max_send;
 	}
-	/* Need UNIX extensions. */
+
+	if (!lp_large_readwrite()) {
+		return req->sconn->smb1.sessions.max_send;
+	}
+
+	if (req_is_in_chain(req)) {
+		return req->sconn->smb1.sessions.max_send;
+	}
+
+	if (req->encrypted) {
+		/*
+		 * Don't take encrypted traffic up to the
+		 * limit. There are padding considerations
+		 * that make that tricky.
+		 */
+		return req->sconn->smb1.sessions.max_send;
+	}
+
+	if (srv_is_signing_active(req->sconn)) {
+		return 0x1FFFF;
+	}
+
 	if (!lp_unix_extensions()) {
-		return false;
+		return 0x1FFFF;
 	}
-	return true;
+
+	/*
+	 * We can do ultra-large POSIX reads.
+	 */
+	return 0xFFFFFF;
+}
+
+/****************************************************************************
+ 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;
+	size_t hdr_len = MIN_SMB_SIZE + VWV(12);
+	size_t max_len = max_pdu - hdr_len;
+
+	/*
+	 * 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;
+	}
+
+	if (req->sconn->conn->protocol < PROTOCOL_NT1) {
+		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_len);
 }
 
 /****************************************************************************
@@ -3913,38 +3971,14 @@ 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()) {
+	smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
+	if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
 		/*
-		 * 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.
+		 * This is a heuristic to avoid keeping large
+		 * outgoing buffers around over long-lived aio
+		 * requests.
 		 */
-		smb_maxcnt |= (upper_size<<16);
-		if (upper_size > 1) {
-			/* Can't do this on a chained packet. */
-			if ((CVAL(req->vwv+0, 0) != 0xFF)) {
-				reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
-				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;
-		}
+		big_readX = True;
 	}
 
 	if (req->wct == 12) {
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 890189c..4728759 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -132,11 +132,12 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 	uint16_t action = 0;
 	NTTIME now = timeval_to_nttime(&req->request_time);
 	struct smbXsrv_session *session = NULL;
+	uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
 	uint32_t client_caps = IVAL(req->vwv+10, 0);
 
 	DEBUG(3,("Doing spnego session setup\n"));
 
-	if (global_client_caps == 0) {
+	if (!sconn->smb1.sessions.done_sesssetup) {
 		global_client_caps = client_caps;
 
 		if (!(global_client_caps & CAP_STATUS32)) {
@@ -377,6 +378,12 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 			return;
 		}
 
+		if (!sconn->smb1.sessions.done_sesssetup) {
+			sconn->smb1.sessions.max_send =
+				MIN(sconn->smb1.sessions.max_send,smb_bufsize);
+		}
+		sconn->smb1.sessions.done_sesssetup = true;
+
 		/* current_user_info is changed on new vuid */
 		reload_services(sconn, conn_snum_used, true);
 	} else if (NT_STATUS_IS_OK(status)) {
@@ -560,7 +567,7 @@ static void setup_new_vc_session(struct smbd_server_connection *sconn)
 void reply_sesssetup_and_X(struct smb_request *req)
 {
 	uint64_t sess_vuid;
-	int smb_bufsize;
+	uint16_t smb_bufsize;
 	DATA_BLOB lm_resp;
 	DATA_BLOB nt_resp;
 	DATA_BLOB plaintext_password;
@@ -671,8 +678,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 		const uint8_t *save_p = req->buf;
 		uint16 byte_count;
 
-
-		if(global_client_caps == 0) {
+		if (!sconn->smb1.sessions.done_sesssetup) {
 			global_client_caps = IVAL(req->vwv+11, 0);
 
 			if (!(global_client_caps & CAP_STATUS32)) {
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 93b9cfd..3c6db30 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -65,7 +65,7 @@ static fstring multishare_conn_fname;
 static bool use_multishare_conn = False;
 static bool do_encrypt;
 static const char *local_path = NULL;
-static int signing_state = SMB_SIGNING_DEFAULT;
+static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
 char *test_filename;
 
 bool torture_showall = False;
@@ -7239,6 +7239,341 @@ 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 = 0x1FFFF;
+
+	if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
+		max_pdu = 0xFFFFFF;
+	}
+
+	if (smb1cli_conn_signing_is_active(cli->conn)) {
+		max_pdu = 0x1FFFF;
+	}
+
+	if (smb1cli_conn_encryption_on(cli->conn)) {
+		max_pdu = CLI_BUFFER_SIZE;
+	}
+
+	if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
+		len_requested &= 0xFFFF;
+	}
+
+	return MIN(len_requested, max_pdu - (MIN_SMB_SIZE + VWV(12)));
+}
+
+static bool check_read_call(struct cli_state *cli,
+			    uint16_t fnum,
+			    uint8_t *buf,
+			    size_t len_requested)
+{
+	NTSTATUS status;
+	struct tevent_req *subreq = 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;
+	}
+
+	subreq = cli_read_andx_send(talloc_tos(),
+				    ev,
+				    cli,
+				    fnum,
+				    0,
+				    len_requested);
+
+	if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
+		return false;
+	}
+
+	status = cli_read_andx_recv(subreq, &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(subreq);
+	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 0x10000 bytes. */
+	if (check_read_call(cli, fnum, buf,    0x10000) == false) {
+		return false;
+	}
+	/* A read of 0x10000 should return 0x10001 bytes. */
+	if (check_read_call(cli, fnum, buf,    0x10001) == false) {
+		return false;
+	}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list