[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Sat Jun 27 05:43:07 UTC 2020


The branch, master has been updated
       via  db10b14c1b7 s3:smbd: fix the handling of the durable_v2_timeout
       via  4ef206b02dd s4:torture/smb2: adjust durable v2 tests to pass against Windows Server 2019
       via  c603a50a484 s4:torture/smb2: remove MULTI_CHANNEL checking from smb2.replay.channel-sequence
       via  f1ecaa75a2f selftest/Samba3: support durable handles on the 'aio' share
       via  303a01d93d9 s3:smb2_lock: implement lock_sequence replay detection
       via  6fc8ed1385a docs-xml/smbdotconf: add "smb2 disable lock sequence checking"
       via  6b5bd280f0f s3:smb2_lock: pass in_lock_sequence to smbd_smb2_lock_send()
       via  5846e482560 s3:smbXsrv_open: initialize smbXsrv_open_global->lock_sequence_array with 0xFF
       via  b2ce954e2d7 s3:smbXsrv.idl: add lock_sequence_array to smbXsrv_open_global0
       via  fdb346b2b39 s4:torture/smb2: add smb2.lock.replay_smb3_specification test
       via  3b1b2e60466 s4:torture/smb2: make smb2.lock.replay_broken_windows more obvious
       via  6b6086bb58c s4:torture/smb2: fix and improve the smb2.lock.replay test
      from  fad2bd8ec7a torture4: openattr always succeeds

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


- Log -----------------------------------------------------------------
commit db10b14c1b793dddcb67eb41adbf869378861216
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 24 18:01:46 2020 +0200

    s3:smbd: fix the handling of the durable_v2_timeout
    
    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): Sat Jun 27 05:42:05 UTC 2020 on sn-devel-184

commit 4ef206b02ddd44a4dbe79c3e7d36554d8d14b1e3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 24 17:48:24 2020 +0200

    s4:torture/smb2: adjust durable v2 tests to pass against Windows Server 2019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit c603a50a48439c89eb08de8766dcfc69610688e1
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 24 17:41:15 2020 +0200

    s4:torture/smb2: remove MULTI_CHANNEL checking from smb2.replay.channel-sequence
    
    This test doesn't need multi-channel. But we need to
    force using the channel_sequence, as our client libraries
    only use them for multi-channel connections or persistent handles.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit f1ecaa75a2f2685f2dcf0836f0d41827de7fa081
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 24 15:55:20 2012 +0200

    selftest/Samba3: support durable handles on the 'aio' share
    
    This means we can test the lock sequence checking via the
    'samba3.smb2.lock aio(nt4_dc)' test.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 303a01d93d9bc6f8de1ae516126f802dce13ab0b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 24 15:55:20 2012 +0200

    s3:smb2_lock: implement lock_sequence replay detection
    
    While windows enables it only for resilient and persistent handles a SMB server
    SHOULD (according to MS-SMB2 section 3.3.5.14 ) activate processing of lock
    sequence numbers:
    
    ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is TRUE or if
    Connection.Dialect belongs to the SMB 3.x dialect family and
    Connection.ServerCapabilities includes SMB2_GLOBAL_CAP_MULTI_CHANNEL ...
    
    We only support durable handles or multichannel, so we only implement
    these according to the specification.
    
    But we have 'smb2 disable lock sequence checking = yes' to force
    to match the Windows Server bahavior, which only supports this
    for resilient and persistent handles.
    
    Pair-Programmed-With: Michael Adam <obnox at samba.org>
    Pair-Programmed-With: Guenther Deschner <gd at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Guenther Deschner <gd at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6fc8ed1385aa8309b7ae6263541505ac978e4591
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 23 18:30:15 2020 +0200

    docs-xml/smbdotconf: add "smb2 disable lock sequence checking"
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6b5bd280f0f85aeb166559fc074cbbfb220911a9
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 24 14:53:05 2012 +0200

    s3:smb2_lock: pass in_lock_sequence to smbd_smb2_lock_send()
    
    Take the value from the client if the dialect is SMB2_10 or higher,
    otherwise default to 0.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 5846e4825604bcc1a15798c5da9f86ca44851b0e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 24 15:17:56 2012 +0200

    s3:smbXsrv_open: initialize smbXsrv_open_global->lock_sequence_array with 0xFF
    
    This is way to mark an entry as invalid (.valid = false).
    
    Pair-Programmed-With: Michael Adam <obnox at samba.org>
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit b2ce954e2d76a81da2bc805b648cb83f50860e21
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 24 15:06:54 2012 +0200

    s3:smbXsrv.idl: add lock_sequence_array to smbXsrv_open_global0
    
    This is needed for lock replay detection.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit fdb346b2b39746888cdd3fb49843a84fea1c1676
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 2 15:30:53 2019 +0200

    s4:torture/smb2: add smb2.lock.replay_smb3_specification test
    
    This implements a test that checks for the specified behaviour.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 3b1b2e604669b481862219224843ee2e016a1f01
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 2 14:51:26 2019 +0200

    s4:torture/smb2: make smb2.lock.replay_broken_windows more obvious
    
    This test checks the SMB 2.1.0 behaviour of lock sequence checking,
    which is only turned on for resilient handles.
    
    Even Windows Server 2019 only implements lock sequence checking only
    for resilient and persistent handles as a server.
    While its client side uses lock sequence checking if it negotiated
    multichannel with the server.
    
    Hopefully this will be fixed in future Windows versions.
    
    Make it clear that this test is supposed to pass against the legacy
    Windows servers which violate the specification:
    
      [MS-SMB2] 3.3.5.14 Receiving an SMB2 LOCK Request
    
      ...
    
      ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is
      TRUE or if Connection.Dialect belongs to the SMB 3.x dialect family
      and Connection.ServerCapabilities includes
      SMB2_GLOBAL_CAP_MULTI_CHANNEL bit, the server SHOULD<314>
      perform lock sequence verification ...
    
      ...
    
      <314> Section 3.3.5.14: Windows 7 and Windows Server 2008 R2 perform
      lock sequence verification only when Open.IsResilient is TRUE.
      Windows 8 through Windows 10 v1909 and Windows Server 2012 through
      Windows Server v1909 perform lock sequence verification only when
      Open.IsResilient or Open.IsPersistent is TRUE.
    
    Note <314> also applies to all versions (at least) up to Windows Server v2004.
    
    Hopefully this will be fixed in future Windows versions and they
    will avoid Note <314>.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6b6086bb58cf185145eeac99f146bf96b5311112
Author: Michael Adam <obnox at samba.org>
Date:   Thu Sep 20 12:45:17 2018 +0200

    s4:torture/smb2: fix and improve the smb2.lock.replay test
    
    The test was wrong in that it used an invalid
    lock sequence bucket (65) where it actually wanted
    to use a valid on (64), and hence the test results
    (which were adapted to the real responses) were not
    quite logical.
    
    This patch fixes this and also improves some of
    the comments so that the flow of the patch becomes
    a little more obvious.
    
    Pair-Programmed-With: Günther Deschner <gd at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Günther Deschner <gd at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 .../smb2_disable_lock_sequence_checking.xml        |  41 +++
 selftest/knownfail                                 |   8 +-
 selftest/target/Samba3.pm                          |   2 +-
 source3/librpc/idl/smbXsrv.idl                     |   1 +
 source3/smbd/smb2_create.c                         |   2 +-
 source3/smbd/smb2_lock.c                           | 123 +++++++-
 source3/smbd/smbXsrv_open.c                        |   7 +
 source4/torture/smb2/durable_v2_open.c             |  26 +-
 source4/torture/smb2/lock.c                        | 343 ++++++++++++++++++++-
 source4/torture/smb2/replay.c                      |  34 +-
 10 files changed, 534 insertions(+), 53 deletions(-)
 create mode 100644 docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml


Changeset truncated at 500 lines:

diff --git a/docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml b/docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml
new file mode 100644
index 00000000000..9ca7187fb51
--- /dev/null
+++ b/docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml
@@ -0,0 +1,41 @@
+<samba:parameter name="smb2 disable lock sequence checking"
+                 context="G"
+                 type="boolean"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+    <para>This boolean parameter controls whether
+    <citerefentry><refentrytitle>smbd</refentrytitle>
+    <manvolnum>8</manvolnum></citerefentry> will disable
+    lock sequence checking even for multi-channel connections
+    as well as durable handles.
+    </para>
+
+    <para>The [MS-SMB2] specification (under 3.3.5.14 Receiving an SMB2 LOCK Request)
+    documents that a server should do lock sequence if Open.IsResilient or Open.IsDurable
+    or Open.IsPersistent is TRUE or if Connection.Dialect belongs to the SMB 3.x dialect
+    family and Connection.ServerCapabilities includes SMB2_GLOBAL_CAP_MULTI_CHANNEL.
+    </para>
+
+    <para>But Windows Server (at least up to v2004) only does these checks
+    for the Open.IsResilient and Open.IsPersistent.
+    That means they do not implement the behavior specified
+    in [MS-SMB2].</para>
+
+    <para>By default Samba behaves according to the specification
+    and sends smb2 oplock break notification retries.</para>
+
+    <para>Warning: Only enable this option if existing clients can't
+    handle lock sequence checking for handles without Open.IsResilient and Open.IsPersistent.
+    And it turns out that the Windows Server behavior is required.</para>
+
+    <para>Note: it's likely that this option will be removed again
+    if future Windows versions change their behavior.</para>
+
+    <para>Note: Samba does not implement Open.IsResilient and Open.IsPersistent yet.</para>
+</description>
+
+<related>server multi channel support</related>
+
+<value type="default">no</value>
+<value type="example">yes</value>
+</samba:parameter>
diff --git a/selftest/knownfail b/selftest/knownfail
index 57a4d93a37d..6fdeec1550d 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -211,10 +211,10 @@
 ^samba3.smb2.session.*reauth5 # some special anonymous checks?
 ^samba3.smb2.compound.interim2 # wrong return code (STATUS_CANCELLED)
 ^samba3.smb2.compound.aio.interim2 # wrong return code (STATUS_CANCELLED)
-^samba3.smb2.replay.channel-sequence
-^samba3.smb2.replay.replay3
-^samba3.smb2.replay.replay4
-^samba3.smb2.lock.*replay
+^samba3.smb2.replay.replay3 # This requires multi-chanel
+^samba3.smb2.replay.replay4 # This requires multi-chanel
+^samba3.smb2.lock.replay_smb3_specification # This requires multi-chanel or durable handles
+^samba3.smb2.lock.*replay_broken_windows # This tests the windows behaviour
 ^samba3.smb2.lease.statopen3
 ^samba3.smb2.lease.unlink # we currently do not downgrade RH lease to R after unlink
 ^samba3.smb2.multichannel
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index d99a59dca73..591c43b7d0a 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -2467,7 +2467,7 @@ sub provision($$)
 	force directory mode = 0
 	vfs objects = xattr_tdb streams_depot
 [aio]
-	copy = tmp
+	copy = durable
 	aio read size = 1
 	aio write size = 1
 
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index bdab9345342..2e8e2bbcd31 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -438,6 +438,7 @@ interface smbXsrv
 		DATA_BLOB				backend_cookie;
 		uint16					channel_sequence;
 		hyper					channel_generation;
+		[flag(NDR_PAHEX)] uint8			lock_sequence_array[64];
 	} smbXsrv_open_global0;
 
 	typedef union {
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index d1ed90284a4..05fa704da72 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -1157,7 +1157,7 @@ static void smbd_smb2_create_before_exec(struct tevent_req *req)
 		 * durable handle v2 request processed below
 		 */
 		state->durable_requested = true;
-		state->durable_timeout_msec = durable_v2_timeout;
+		state->durable_timeout_msec = MIN(durable_v2_timeout, 300*1000);
 		if (state->durable_timeout_msec == 0) {
 			/*
 			 * Set the timeout to 1 min as default.
diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c
index 97e5e994e4e..80a174cb293 100644
--- a/source3/smbd/smb2_lock.c
+++ b/source3/smbd/smb2_lock.c
@@ -47,12 +47,15 @@ struct smbd_smb2_lock_state {
 	uint32_t retry_msecs;
 	uint16_t lock_count;
 	struct smbd_lock_element *locks;
+	uint8_t lock_sequence_value;
+	uint8_t *lock_sequence_element;
 };
 
 static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
 						 struct tevent_context *ev,
 						 struct smbd_smb2_request *smb2req,
 						 struct files_struct *in_fsp,
+						 uint32_t in_lock_sequence,
 						 uint16_t in_lock_count,
 						 struct smbd_smb2_lock_element *in_locks);
 static NTSTATUS smbd_smb2_lock_recv(struct tevent_req *req);
@@ -62,6 +65,7 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
 {
 	const uint8_t *inbody;
 	uint16_t in_lock_count;
+	uint32_t in_lock_sequence;
 	uint64_t in_file_id_persistent;
 	uint64_t in_file_id_volatile;
 	struct files_struct *in_fsp;
@@ -78,7 +82,12 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
 	inbody = SMBD_SMB2_IN_BODY_PTR(req);
 
 	in_lock_count			= CVAL(inbody, 0x02);
-	/* 0x04 - 4 bytes reserved */
+	if (req->xconn->protocol >= PROTOCOL_SMB2_10) {
+		in_lock_sequence	= IVAL(inbody, 0x04);
+	} else {
+		/* 0x04 - 4 bytes reserved */
+		in_lock_sequence	= 0;
+	}
 	in_file_id_persistent		= BVAL(inbody, 0x08);
 	in_file_id_volatile		= BVAL(inbody, 0x10);
 
@@ -139,6 +148,7 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
 
 	subreq = smbd_smb2_lock_send(req, req->sconn->ev_ctx,
 				     req, in_fsp,
+				     in_lock_sequence,
 				     in_lock_count,
 				     in_locks);
 	if (subreq == NULL) {
@@ -191,6 +201,8 @@ static void smbd_smb2_request_lock_done(struct tevent_req *subreq)
 	}
 }
 
+static void smbd_smb2_lock_cleanup(struct tevent_req *req,
+				   enum tevent_req_state req_state);
 static void smbd_smb2_lock_try(struct tevent_req *req);
 static void smbd_smb2_lock_retry(struct tevent_req *subreq);
 static bool smbd_smb2_lock_cancel(struct tevent_req *req);
@@ -199,6 +211,7 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
 						 struct tevent_context *ev,
 						 struct smbd_smb2_request *smb2req,
 						 struct files_struct *fsp,
+						 uint32_t in_lock_sequence,
 						 uint16_t in_lock_count,
 						 struct smbd_smb2_lock_element *in_locks)
 {
@@ -208,6 +221,8 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
 	uint16_t i;
 	struct smbd_lock_element *locks;
 	NTSTATUS status;
+	bool check_lock_sequence = false;
+	uint32_t lock_sequence_bucket = 0;
 
 	req = tevent_req_create(mem_ctx, &state,
 			struct smbd_smb2_lock_state);
@@ -219,6 +234,8 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
 	state->smb2req = smb2req;
 	smb2req->subreq = req; /* So we can find this when going async. */
 
+	tevent_req_set_cleanup_fn(req, smbd_smb2_lock_cleanup);
+
 	state->smb1req = smbd_smb2_fake_smb_request(smb2req);
 	if (tevent_req_nomem(state->smb1req, req)) {
 		return tevent_req_post(req, ev);
@@ -227,6 +244,91 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
 	DEBUG(10,("smbd_smb2_lock_send: %s - %s\n",
 		  fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
 
+	/*
+	 * Windows sets check_lock_sequence = true
+	 * only for resilient and persistent handles.
+	 *
+	 * [MS-SMB2] 3.3.5.14 Receiving an SMB2 LOCK Request
+	 *
+	 *  ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is
+	 *  TRUE or if Connection.Dialect belongs to the SMB 3.x dialect family
+	 *  and Connection.ServerCapabilities includes
+	 *  SMB2_GLOBAL_CAP_MULTI_CHANNEL bit, the server SHOULD<314>
+	 *  perform lock sequence * verification ...
+
+	 *  <314> Section 3.3.5.14: Windows 7 and Windows Server 2008 R2 perform
+	 *  lock sequence verification only when Open.IsResilient is TRUE.
+	 *  Windows 8 through Windows 10 v1909 and Windows Server 2012 through
+	 *  Windows Server v1909 perform lock sequence verification only when
+	 *  Open.IsResilient or Open.IsPersistent is TRUE.
+	 *
+	 * Note <314> also applies to all versions (at least) up to
+	 * Windows Server v2004.
+	 *
+	 * Hopefully this will be fixed in future Windows versions and they
+	 * will avoid Note <314>.
+	 *
+	 * We implement what the specification says by default, but
+	 * allow "smb2 disable lock sequence checking = yes" to
+	 * behave like Windows again.
+	 *
+	 * Note: that we already check the dialect before setting
+	 * SMB2_CAP_MULTI_CHANNEL in smb2_negprot.c
+	 */
+	if (smb2req->xconn->smb2.server.capabilities & SMB2_CAP_MULTI_CHANNEL) {
+		check_lock_sequence = true;
+	}
+	if (fsp->op->global->durable) {
+		check_lock_sequence = true;
+	}
+
+	if (check_lock_sequence) {
+		bool disable_lock_sequence_checking =
+			lp_smb2_disable_lock_sequence_checking();
+
+		if (disable_lock_sequence_checking) {
+			check_lock_sequence = false;
+		}
+	}
+
+	if (check_lock_sequence) {
+		state->lock_sequence_value = in_lock_sequence & 0xF;
+		lock_sequence_bucket = in_lock_sequence >> 4;
+	}
+	if ((lock_sequence_bucket > 0) &&
+	    (lock_sequence_bucket <= sizeof(fsp->op->global->lock_sequence_array)))
+	{
+		uint32_t idx = lock_sequence_bucket - 1;
+		uint8_t *array = fsp->op->global->lock_sequence_array;
+
+		state->lock_sequence_element = &array[idx];
+	}
+
+	if (state->lock_sequence_element != NULL) {
+		/*
+		 * The incoming 'state->lock_sequence_value' is masked with 0xF.
+		 *
+		 * Note per default '*state->lock_sequence_element'
+		 * is invalid, a value of 0xFF that can never match on
+		 * incoming value.
+		 */
+		if (*state->lock_sequence_element == state->lock_sequence_value)
+		{
+			DBG_INFO("replayed smb2 lock request detected: "
+				 "file %s, value %u, bucket %u\n",
+				 fsp_str_dbg(fsp),
+				 (unsigned)state->lock_sequence_value,
+				 (unsigned)lock_sequence_bucket);
+			tevent_req_done(req);
+			return tevent_req_post(req, ev);
+		}
+		/*
+		 * If it's not a replay, mark the element as
+		 * invalid again.
+		 */
+		*state->lock_sequence_element = 0xFF;
+	}
+
 	locks = talloc_array(state, struct smbd_lock_element, in_lock_count);
 	if (locks == NULL) {
 		tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
@@ -374,6 +476,25 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
 	return req;
 }
 
+static void smbd_smb2_lock_cleanup(struct tevent_req *req,
+				   enum tevent_req_state req_state)
+{
+	struct smbd_smb2_lock_state *state = tevent_req_data(
+		req, struct smbd_smb2_lock_state);
+
+	if (req_state != TEVENT_REQ_DONE) {
+		return;
+	}
+
+	if (state->lock_sequence_element != NULL) {
+		/*
+		 * On success we remember the given/incoming
+		 * value (which was masked with 0xF.
+		 */
+		*state->lock_sequence_element = state->lock_sequence_value;
+	}
+}
+
 static void smbd_smb2_lock_update_retry_msecs(
 	struct smbd_smb2_lock_state *state)
 {
diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c
index b7b08e76c31..5180315449d 100644
--- a/source3/smbd/smbXsrv_open.c
+++ b/source3/smbd/smbXsrv_open.c
@@ -526,6 +526,13 @@ static NTSTATUS smbXsrv_open_global_allocate(struct db_context *db,
 	}
 	talloc_set_destructor(global, smbXsrv_open_global_destructor);
 
+	/*
+	 * We mark every slot as invalid using 0xFF.
+	 * Valid values are masked with 0xF.
+	 */
+	memset(global->lock_sequence_array, 0xFF,
+	       sizeof(global->lock_sequence_array));
+
 	/*
 	 * Here we just randomly try the whole 32-bit space
 	 *
diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c
index b2c519db3f6..014ff192ad1 100644
--- a/source4/torture/smb2/durable_v2_open.c
+++ b/source4/torture/smb2/durable_v2_open.c
@@ -123,7 +123,7 @@ bool test_durable_v2_open_create_blob(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 
 	/* disconnect */
 	TALLOC_FREE(tree);
@@ -547,7 +547,7 @@ bool test_durable_v2_open_reopen1(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 
 	/* try a durable reconnect while the file is still open */
 	ZERO_STRUCT(io);
@@ -623,7 +623,7 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 
 	/*
 	 * a session reconnect on a second tcp connection
@@ -666,7 +666,7 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 0);
 	_h = io.out.file.handle;
 	h = &_h;
 
@@ -710,7 +710,7 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 0);
 	_h = io.out.file.handle;
 	h = &_h;
 
@@ -795,7 +795,7 @@ bool test_durable_v2_open_reopen1a_lease(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
 	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease_key);
 	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease_key);
@@ -885,7 +885,7 @@ bool test_durable_v2_open_reopen1a_lease(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 0);
 	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
 	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease_key);
 	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease_key);
@@ -961,7 +961,7 @@ bool test_durable_v2_open_reopen2(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 
 	/* disconnect, leaving the durable open */
 	TALLOC_FREE(tree);
@@ -1122,7 +1122,7 @@ bool test_durable_v2_open_reopen2b(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 
 	/* disconnect, leaving the durable open */
 	TALLOC_FREE(tree);
@@ -1294,7 +1294,7 @@ bool test_durable_v2_open_reopen2_lease(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
 	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease_key);
 	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease_key);
@@ -1547,7 +1547,7 @@ bool test_durable_v2_open_reopen2_lease_v2(struct torture_context *tctx,
 	CHECK_VAL(io.out.durable_open, false);
 	CHECK_VAL(io.out.durable_open_v2, true);
 	CHECK_VAL(io.out.persistent_open, false);
-	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.timeout, 300*1000);
 	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
 	CHECK_VAL(io.out.lease_response_v2.lease_key.data[0], lease_key);
 	CHECK_VAL(io.out.lease_response_v2.lease_key.data[1], ~lease_key);
@@ -1787,7 +1787,7 @@ bool test_durable_v2_open_app_instance(struct torture_context *tctx,
 	CHECK_VAL(io1.out.durable_open, false);
 	CHECK_VAL(io1.out.durable_open_v2, true);
 	CHECK_VAL(io1.out.persistent_open, false);
-	CHECK_VAL(io1.out.timeout, io1.in.timeout);
+	CHECK_VAL(io1.out.timeout, 300*1000);
 
 	/*
 	 * try to open the file as durable from a second tree with
@@ -1814,7 +1814,7 @@ bool test_durable_v2_open_app_instance(struct torture_context *tctx,
 	CHECK_VAL(io2.out.durable_open, false);
 	CHECK_VAL(io2.out.durable_open_v2, true);
 	CHECK_VAL(io2.out.persistent_open, false);
-	CHECK_VAL(io2.out.timeout, io2.in.timeout);
+	CHECK_VAL(io2.out.timeout, 300*1000);
 
 	CHECK_VAL(break_info.count, 0);
 
diff --git a/source4/torture/smb2/lock.c b/source4/torture/smb2/lock.c
index 8dca75cc6c1..1c515c865e5 100644
--- a/source4/torture/smb2/lock.c
+++ b/source4/torture/smb2/lock.c
@@ -2873,9 +2873,38 @@ done:
 
 /**
  * Test lock replay detection
+ *
+ * This test checks the SMB 2.1.0 behaviour of lock sequence checking,
+ * which is only turned on for resilient handles.
+ *
+ * Make it clear that this test is supposed to pass against the legacy
+ * Windows servers which violate the specification:
+ *
+ *   [MS-SMB2] 3.3.5.14 Receiving an SMB2 LOCK Request
+ *
+ *   ...
+ *
+ *   ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is
+ *   TRUE or if Connection.Dialect belongs to the SMB 3.x dialect family
+ *   and Connection.ServerCapabilities includes
+ *   SMB2_GLOBAL_CAP_MULTI_CHANNEL bit, the server SHOULD<314>
+ *   perform lock sequence verification ...
+ *
+ *   ...
+ *
+ *   <314> Section 3.3.5.14: Windows 7 and Windows Server 2008 R2 perform
+ *   lock sequence verification only when Open.IsResilient is TRUE.
+ *   Windows 8 through Windows 10 v1909 and Windows Server 2012 through
+ *   Windows Server v1909 perform lock sequence verification only when
+ *   Open.IsResilient or Open.IsPersistent is TRUE.
+ *
+ * Note <314> also applies to all versions (at least) up to Windows Server v2004.
+ *
+ * Hopefully this will be fixed in future Windows versions and they
+ * will avoid Note <314>.
  */
-static bool test_replay(struct torture_context *torture,
-			  struct smb2_tree *tree)
+static bool test_replay_broken_windows(struct torture_context *torture,
+				       struct smb2_tree *tree)
 {
 	NTSTATUS status;
 	bool ret = true;
@@ -2884,11 +2913,11 @@ static bool test_replay(struct torture_context *torture,
 	struct smb2_lock lck;
 	struct smb2_lock_element el;
 	uint8_t res_req[8];
-	const char *fname = BASEDIR "\\replay.txt";
+	const char *fname = BASEDIR "\\replay_broken_windows.txt";
 	struct smb2_transport *transport = tree->session->transport;
 
 	if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB2_10) {


-- 
Samba Shared Repository



More information about the samba-cvs mailing list