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 <[email protected]>
Date:   Wed Mar 20 08:49:20 2013 +0100

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

commit c9066b057a6aa3cc1960124c9f2519413a2b57da
Author: Stefan Metzmacher <[email protected]>
Date:   Tue Mar 19 17:11:03 2013 +0100

    s4:torture: raw.read fix large reads against windows
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit df618e33ac011c018374af8da021c7b5f1cc1427
Author: Jeremy Allison <[email protected]>
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 <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit d9afb2b14df642de5d9225d10cc20cac7fd5133f
Author: Jeremy Allison <[email protected]>
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 <[email protected]>
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 5a05e687ce724ea808cdb1e6627b9c67804eb879
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Mar 18 19:50:38 2013 +0100

    s4:smb_server: fix large read_andx requests
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit fd88520497b4043e9d81656f7cb56a7b25245c2a
Author: Jeremy Allison <[email protected]>
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 <[email protected]>
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 21707defe06e1db18a6645b0b56db4178e3df5f6
Author: Jeremy Allison <[email protected]>
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 <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 36f6a8abb2ad0c7d0551679cc61a29fa2dc16d80
Author: Jeremy Allison <[email protected]>
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 <[email protected]>
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit b80111adb3a30ff386b3c45fcf962c417256bb59
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Mar 18 12:36:30 2013 +0100

    s3:smbd: add some const to req_is_in_chain()
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit be98c1c889166a5f2b83e1e29d7dcbbaf6baab8f
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit d24b8afb79f75b1db9301b79862be484a4932979
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit 40c3db9b6a584a6c243fd02b12269d54e7425fea
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit 1111d46cc52e868cf4894909b71f1574196e2887
Author: Jeremy Allison <[email protected]>
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 <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 53d348dff082f9c18e06f99ec646127467f339e7
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit b041dc9451e210acc82a82b75e02e4166d8973d5
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

commit 3d7a4db6bc5cd42432393bf69622c435e67e811f
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

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

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

Reply via email to