[SCM] Samba Shared Repository - branch master updated

Michael Adam obnox at samba.org
Thu Mar 3 15:22:04 UTC 2016


The branch, master has been updated
       via  116f415 heimdal asn1: avoid fclose(NULL) caused by missing braces
       via  c9836e8 regtree: avoid GCC indentation warning
       via  272d06d smbd:smb2: move op variable into scope of use in smb2_create_send
       via  2fd54b5 smbd:smb2: implement create replay
       via  03a3aa9 smbXsrv.idl: add create_action to smbXsrv_open
       via  5b90c98 smbXsrv:open: add smb2srv_open_lookup_replay_cache()
       via  08e3483 smb2:create: create replay cache when request has a create_guid
       via  4370bda smbXsrv:open: maintain a replay cache
       via  1eb5f1e librpc:smbXsrv.idl: add flags to smbXsrv_open
       via  6251d92 smbd:smb2: allow the REPLAY_OPERATION flag for SMB3+ requests
       via  1b804d6 torture:smb2: add smb2.replay.replay-dhv2-lease3
       via  1c77298 torture:smb2: add smb2.replay.replay-oplock-lease
       via  2036e1d torture:smb2: add smb2.replay.replay-dhv2-lease-oplock
       via  6eeabe4 torture:smb2: add smb2.replay.replay-dhv2-lease2
       via  de678eb torture:smb2: add smb2.replay.replay-dhv2-lease1
       via  6eac2ae torture:smb2:replay: extend CHECK_CREATE_OUT() to know leases
       via  9ac9d28 torture:smb2: split rename2 into multiple tests and extend these
       via  9ebf079 torture:smb2: rename replay1 -> replay-commands
      from  8e870dd vfs: remove an outdate comment from the files_struct definition

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


- Log -----------------------------------------------------------------
commit 116f41577901951893cd2832d4ba963c7dd877dd
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 3 09:33:38 2016 +1300

    heimdal asn1: avoid fclose(NULL) caused by missing braces
    
    Thanks to GCC6 -Wmisleading-indentation.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>
    
    Autobuild-User(master): Michael Adam <obnox at samba.org>
    Autobuild-Date(master): Thu Mar  3 16:21:52 CET 2016 on sn-devel-144

commit c9836e812103eb099a4ad39493917d0726a58279
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 3 09:31:32 2016 +1300

    regtree: avoid GCC indentation warning
    
    This was not actually a bug, but GCC6 (sort of reasonably) thought it could be.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit 272d06d40b7338de7db8954192f42c7340753920
Author: Michael Adam <obnox at samba.org>
Date:   Thu Mar 3 09:27:42 2016 +0100

    smbd:smb2: move op variable into scope of use in smb2_create_send
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 2fd54b533292e54de8c289fb093748fb171c15a7
Author: Michael Adam <obnox at samba.org>
Date:   Sun Feb 28 02:32:36 2016 +0100

    smbd:smb2: implement create replay
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 03a3aa981500c5ba9d82c27f36e107672b071203
Author: Michael Adam <obnox at samba.org>
Date:   Mon Feb 29 02:11:26 2016 +0100

    smbXsrv.idl: add create_action to smbXsrv_open
    
    Needed for create replay.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 5b90c986eda8201660434a9a1d64e5a0a625379e
Author: Michael Adam <obnox at samba.org>
Date:   Sat Feb 27 03:23:27 2016 +0100

    smbXsrv:open: add smb2srv_open_lookup_replay_cache()
    
    A function to find an open from the replay cache,
    based on the create_guid handed in.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 08e34830b7f4d631a24e94aad1502949eb2cd675
Author: Michael Adam <obnox at samba.org>
Date:   Fri Feb 26 13:53:25 2016 +0100

    smb2:create: create replay cache when request has a create_guid
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 4370bda3c0f35c1cc9b45a004bb829b1d69a4e38
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 24 00:23:15 2016 +0100

    smbXsrv:open: maintain a replay cache
    
    This caches a map create_guid -> file_id, so that
    a replayed create can find the already created
    open again.
    
    This is automatically deleted once the first use
    of the file handle is happening (triggered by
    the lookup for the file-id).
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1eb5f1e42276999f0f4fc73cac03a188fb6d83e9
Author: Michael Adam <obnox at samba.org>
Date:   Fri Feb 26 13:44:13 2016 +0100

    librpc:smbXsrv.idl: add flags to smbXsrv_open
    
    These flags reflect the need for and state of the replay cache.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6251d926e0cdd37ed312f7dc78ce2735e979c25f
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 24 15:53:57 2016 +0100

    smbd:smb2: allow the REPLAY_OPERATION flag for SMB3+ requests
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1b804d6f93fec74af45e89465fc7316917a3b64f
Author: Michael Adam <obnox at samba.org>
Date:   Wed Mar 2 20:45:16 2016 +0100

    torture:smb2: add smb2.replay.replay-dhv2-lease3
    
    create with a lease, and replay with lease
    with a different lease key.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1c772984c64e79b3da9851be29a26714ed209343
Author: Michael Adam <obnox at samba.org>
Date:   Wed Mar 2 01:38:24 2016 +0100

    torture:smb2: add smb2.replay.replay-oplock-lease
    
    create with an oplock, and replay with a lease.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2036e1d27b7dde091531c4a8a516212e4b489df2
Author: Michael Adam <obnox at samba.org>
Date:   Tue Mar 1 23:03:50 2016 +0100

    torture:smb2: add smb2.replay.replay-dhv2-lease-oplock
    
    Open with a lease and replay with an oplock.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6eeabe43a2378a832dc21a1d8acdaf18b0dbc889
Author: Michael Adam <obnox at samba.org>
Date:   Mon Feb 29 19:04:32 2016 +0100

    torture:smb2: add smb2.replay.replay-dhv2-lease2
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit de678ebcdfda49d373d6151d362074ad66bf280e
Author: Michael Adam <obnox at samba.org>
Date:   Mon Feb 29 18:23:04 2016 +0100

    torture:smb2: add smb2.replay.replay-dhv2-lease1
    
    This is a variant of the replay-dhv2-oplock1 test for leases
    instead of for oplocks.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6eac2ae984c244d9e92876bf29a18a3807352277
Author: Michael Adam <obnox at samba.org>
Date:   Mon Feb 29 19:00:42 2016 +0100

    torture:smb2:replay: extend CHECK_CREATE_OUT() to know leases
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 9ac9d286b4584388b10d2c6247094aed8b0e68a6
Author: Michael Adam <obnox at samba.org>
Date:   Tue Mar 1 01:18:03 2016 +0100

    torture:smb2: split rename2 into multiple tests and extend these
    
    - replay-regular
    - replay-dhv2-oplock1
    - replay-dhv2-oplock2
    - replay-dhv2-oplock3
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 9ebf079b00b642c5df47fecffc3ff1fc96525235
Author: Michael Adam <obnox at samba.org>
Date:   Tue Mar 1 01:14:48 2016 +0100

    torture:smb2: rename replay1 -> replay-commands
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 selftest/knownfail                   |    2 -
 source3/librpc/idl/smbXsrv.idl       |    7 +
 source3/smbd/globals.h               |    4 +
 source3/smbd/smb2_create.c           |  107 +++-
 source3/smbd/smb2_server.c           |    3 +
 source3/smbd/smbXsrv_open.c          |  155 ++++-
 source4/heimdal/lib/asn1/gen.c       |    3 +-
 source4/lib/registry/tools/regtree.c |    3 +-
 source4/torture/smb2/replay.c        | 1092 ++++++++++++++++++++++++++++++++--
 9 files changed, 1303 insertions(+), 73 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/knownfail b/selftest/knownfail
index 04a0621..1ac99d4 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -202,8 +202,6 @@
 ^samba3.smb2.setinfo.setinfo
 ^samba3.smb2.session.*reauth5 # some special anonymous checks?
 ^samba3.smb2.compound.interim2 # wrong return code (STATUS_CANCELLED)
-^samba3.smb2.replay.replay1
-^samba3.smb2.replay.replay2
 ^samba3.smb2.replay.replay3
 ^samba3.smb2.replay.replay4
 ^samba3.smb2.lock.*replay
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index fe86545..4c6895a 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -404,6 +404,11 @@ interface smbXsrv
 
 	/* open files */
 
+	typedef [public,bitmap8bit] bitmap {
+		SMBXSRV_OPEN_NEED_REPLAY_CACHE		= 0x01,
+		SMBXSRV_OPEN_HAVE_REPLAY_CACHE		= 0x02
+	} smbXsrv_open_flags;
+
 	typedef struct {
 		[ignore] db_record 			*db_rec;
 		server_id				server_id;
@@ -463,6 +468,8 @@ interface smbXsrv
 		NTSTATUS				status;
 		NTTIME					idle_time;
 		[ignore] files_struct			*compat;
+		smbXsrv_open_flags			flags;
+		uint32					create_action;
 	} smbXsrv_open;
 
 	typedef union {
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 1ca1389..c843f5a 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -641,6 +641,10 @@ NTSTATUS smb2srv_open_lookup(struct smbXsrv_connection *conn,
 			     uint64_t volatile_id,
 			     NTTIME now,
 			     struct smbXsrv_open **_open);
+NTSTATUS smb2srv_open_lookup_replay_cache(struct smbXsrv_connection *conn,
+					  const struct GUID *create_guid,
+					  NTTIME now,
+					  struct smbXsrv_open **_open);
 NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn,
 			       struct auth_session_info *session_info,
 			       uint64_t persistent_id,
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 7917d42..17bddc1 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -474,7 +474,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 	struct smb2_create_blob *dhnq = NULL;
 	struct smb2_create_blob *dh2q = NULL;
 	struct smb2_create_blob *rqls = NULL;
-	struct smbXsrv_open *op = NULL;
+	bool replay_operation = false;
 
 	if(lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
 		requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
@@ -668,6 +668,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 		struct smb2_lease lease;
 		struct smb2_lease *lease_ptr = NULL;
 		ssize_t lease_len = -1;
+		bool need_replay_cache = false;
+		struct smbXsrv_open *op = NULL;
 #if 0
 		struct smb2_create_blob *svhdx = NULL;
 #endif
@@ -778,6 +780,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 			const uint8_t *p = dh2q->data.data;
 			uint32_t durable_v2_timeout = 0;
 			DATA_BLOB create_guid_blob;
+			const uint8_t *hdr;
+			uint32_t flags;
 
 			if (dh2q->data.length != 32) {
 				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -804,6 +808,12 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 			update_open = true;
 
 			/*
+			 * And we need to create a cache for replaying the
+			 * create.
+			 */
+			need_replay_cache = true;
+
+			/*
 			 * durable handle v2 request processed below
 			 */
 			durable_requested = true;
@@ -816,6 +826,38 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 				 */
 				durable_timeout_msec = (60*1000);
 			}
+
+			/*
+			 * Check for replay operation.
+			 * Only consider it when we have dh2q.
+			 * If we do not have a replay operation, verify that
+			 * the create_guid is not cached for replay.
+			 */
+			hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
+			flags = IVAL(hdr, SMB2_HDR_FLAGS);
+			replay_operation =
+				!!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION);
+
+			status = smb2srv_open_lookup_replay_cache(
+					smb2req->xconn, create_guid,
+					0 /* now */, &op);
+
+			if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+				replay_operation = false;
+			} else if (tevent_req_nterror(req, status)) {
+				DBG_WARNING("smb2srv_open_lookup_replay_cache "
+					    "failed: %s\n", nt_errstr(status));
+				return tevent_req_post(req, ev);
+			} else if (!replay_operation) {
+				/*
+				 * If a create without replay operation flag
+				 * is sent but with a create_guid that is
+				 * currently in the replay cache -- fail.
+				 */
+				status = NT_STATUS_DUPLICATE_OBJECTID;
+				(void)tevent_req_nterror(req, status);
+				return tevent_req_post(req, ev);
+			}
 		}
 
 		if (dhnc) {
@@ -911,6 +953,32 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 				DEBUG(10, ("v2 lease key only for SMB3\n"));
 				lease_ptr = NULL;
 			}
+
+			/*
+			 * Replay with a lease is only allowed if the
+			 * established open carries a lease with the
+			 * same lease key.
+			 */
+			if (replay_operation) {
+				struct smb2_lease *op_ls =
+						&op->compat->lease->lease;
+				int op_oplock = op->compat->oplock_type;
+
+				if (map_samba_oplock_levels_to_smb2(op_oplock)
+				    != SMB2_OPLOCK_LEVEL_LEASE)
+				{
+					status = NT_STATUS_ACCESS_DENIED;
+					(void)tevent_req_nterror(req, status);
+					return tevent_req_post(req, ev);
+				}
+				if (!smb2_lease_key_equal(&lease.lease_key,
+							  &op_ls->lease_key))
+				{
+					status = NT_STATUS_ACCESS_DENIED;
+					(void)tevent_req_nterror(req, status);
+					return tevent_req_post(req, ev);
+				}
+			}
 		}
 
 		/* these are ignored for SMB2 */
@@ -923,9 +991,16 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 
 		/*
 		 * For the backend file open procedure, there are
-		 * two possible modes: durable_reconnect or not.
+		 * three possible modes: replay operation (in which case
+		 * there is nothing else to do), durable_reconnect or
+		 * new open.
 		 */
-		if (do_durable_reconnect) {
+		if (replay_operation) {
+			result = op->compat;
+			result->op = op;
+			update_open = false;
+			info = op->create_action;
+		} else if (do_durable_reconnect) {
 			DATA_BLOB new_cookie = data_blob_null;
 			NTTIME now = timeval_to_nttime(&smb2req->request_time);
 
@@ -1135,7 +1210,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 			}
 		}
 
-		if (durable_requested &&
+		if (!replay_operation && durable_requested &&
 		    (fsp_lease_type(result) & SMB2_LEASE_HANDLE))
 		{
 			status = SMB_VFS_DURABLE_COOKIE(result,
@@ -1145,7 +1220,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 				op->global->backend_cookie = data_blob_null;
 			}
 		}
-		if (op->global->backend_cookie.length > 0) {
+		if (!replay_operation && op->global->backend_cookie.length > 0)
+		{
 			update_open = true;
 
 			op->global->durable = true;
@@ -1154,6 +1230,9 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 
 		if (update_open) {
 			op->global->create_guid = _create_guid;
+			if (need_replay_cache) {
+				op->flags |= SMBXSRV_OPEN_NEED_REPLAY_CACHE;
+			}
 
 			status = smbXsrv_open_update(op);
 			DEBUG(10, ("smb2_create_send: smbXsrv_open_update "
@@ -1179,7 +1258,18 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 			}
 		}
 
-		if (dh2q && op->global->durable) {
+		if (dh2q && op->global->durable &&
+		    /*
+		     * For replay operations, we return the dh2q blob
+		     * in the case of oplocks not based on the state of
+		     * the open, but on whether it could have been granted
+		     * for the request data. In the case of leases instead,
+		     * the state of the open is used...
+		     */
+		    (!replay_operation ||
+		     in_oplock_level == SMB2_OPLOCK_LEVEL_BATCH ||
+		     in_oplock_level == SMB2_OPLOCK_LEVEL_LEASE))
+		{
 			uint8_t p[8] = { 0, };
 			DATA_BLOB blob = data_blob_const(p, sizeof(p));
 			uint32_t durable_v2_response_flags = 0;
@@ -1251,7 +1341,9 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 
 	smb2req->compat_chain_fsp = smb1req->chain_fsp;
 
-	if(lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
+	if (replay_operation) {
+		state->out_oplock_level = in_oplock_level;
+	} else if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
 		state->out_oplock_level	= in_oplock_level;
 	} else {
 		state->out_oplock_level	= map_samba_oplock_levels_to_smb2(result->oplock_type);
@@ -1263,6 +1355,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 	} else {
 		state->out_create_action = info;
 	}
+	result->op->create_action = state->out_create_action;
 	state->out_file_attributes = dos_mode(result->conn,
 					   result->fsp_name);
 
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index ac922a1..68d637e 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2225,6 +2225,9 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 	if (opcode == SMB2_OP_CANCEL) {
 		allowed_flags |= SMB2_HDR_FLAG_ASYNC;
 	}
+	if (xconn->protocol >= PROTOCOL_SMB2_22) {
+		allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
+	}
 	if ((flags & ~allowed_flags) != 0) {
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c
index ee35f2d..a7cea18 100644
--- a/source3/smbd/smbXsrv_open.c
+++ b/source3/smbd/smbXsrv_open.c
@@ -34,6 +34,7 @@
 struct smbXsrv_open_table {
 	struct {
 		struct db_context *db_ctx;
+		struct db_context *replay_cache_db_ctx;
 		uint32_t lowest_id;
 		uint32_t highest_id;
 		uint32_t max_opens;
@@ -225,6 +226,11 @@ static NTSTATUS smbXsrv_open_table_init(struct smbXsrv_connection *conn,
 		TALLOC_FREE(table);
 		return NT_STATUS_NO_MEMORY;
 	}
+	table->local.replay_cache_db_ctx = db_open_rbt(table);
+	if (table->local.replay_cache_db_ctx == NULL) {
+		TALLOC_FREE(table);
+		return NT_STATUS_NO_MEMORY;
+	}
 	table->local.lowest_id = lowest_id;
 	table->local.highest_id = highest_id;
 	table->local.max_opens = max_opens;
@@ -928,6 +934,79 @@ uint32_t smbXsrv_open_hash(struct smbXsrv_open *_open)
 	return ret;
 }
 
+static NTSTATUS smbXsrv_open_set_replay_cache(struct smbXsrv_open *op)
+{
+	struct GUID *create_guid;
+	struct GUID_txt_buf buf;
+	char *guid_string;
+	struct db_context *db = op->table->local.replay_cache_db_ctx;
+	NTSTATUS status;
+
+	if (!(op->flags & SMBXSRV_OPEN_NEED_REPLAY_CACHE)) {
+		return NT_STATUS_OK;
+	}
+
+	if (op->flags & SMBXSRV_OPEN_HAVE_REPLAY_CACHE) {
+		return NT_STATUS_OK;
+	}
+
+	create_guid = &op->global->create_guid;
+	if (GUID_all_zero(create_guid)) {
+		return NT_STATUS_OK;
+	}
+
+	guid_string = GUID_buf_string(create_guid, &buf);
+	if (guid_string == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	status = dbwrap_store_uint32_bystring(db, guid_string, op->local_id);
+
+	if (NT_STATUS_IS_OK(status)) {
+		op->flags |= SMBXSRV_OPEN_HAVE_REPLAY_CACHE;
+		op->flags &= ~SMBXSRV_OPEN_NEED_REPLAY_CACHE;
+	}
+
+	return status;
+}
+
+static NTSTATUS smbXsrv_open_clear_replay_cache(struct smbXsrv_open *op)
+{
+	struct GUID *create_guid;
+	struct GUID_txt_buf buf;
+	char *guid_string;
+	struct db_context *db;
+	NTSTATUS status;
+
+	if (op->table == NULL) {
+		return NT_STATUS_OK;
+	}
+
+	db = op->table->local.replay_cache_db_ctx;
+
+	if (!(op->flags & SMBXSRV_OPEN_HAVE_REPLAY_CACHE)) {
+		return NT_STATUS_OK;
+	}
+
+	create_guid = &op->global->create_guid;
+	if (GUID_all_zero(create_guid)) {
+		return NT_STATUS_OK;
+	}
+
+	guid_string = GUID_buf_string(create_guid, &buf);
+	if (guid_string == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	status = dbwrap_purge_bystring(db, guid_string);
+
+	if (NT_STATUS_IS_OK(status)) {
+		op->flags &= ~SMBXSRV_OPEN_HAVE_REPLAY_CACHE;
+	}
+
+	return status;
+}
+
 NTSTATUS smbXsrv_open_update(struct smbXsrv_open *op)
 {
 	struct smbXsrv_open_table *table = op->table;
@@ -957,6 +1036,13 @@ NTSTATUS smbXsrv_open_update(struct smbXsrv_open *op)
 		return status;
 	}
 
+	status = smbXsrv_open_set_replay_cache(op);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("smbXsrv_open_set_replay_cache failed: %s\n",
+			nt_errstr(status));
+		return status;
+	}
+
 	if (CHECK_DEBUGLVL(10)) {
 		struct smbXsrv_openB open_blob;
 
@@ -980,8 +1066,14 @@ NTSTATUS smbXsrv_open_close(struct smbXsrv_open *op, NTTIME now)
 	NTSTATUS status;
 	NTSTATUS error = NT_STATUS_OK;
 
+	error = smbXsrv_open_clear_replay_cache(op);
+	if (!NT_STATUS_IS_OK(error)) {
+		DBG_ERR("smbXsrv_open_clear_replay_cache failed: %s\n",
+			nt_errstr(error));
+	}
+
 	if (op->table == NULL) {
-		return NT_STATUS_OK;
+		return error;
 	}
 
 	table = op->table;
@@ -1157,6 +1249,7 @@ NTSTATUS smb2srv_open_lookup(struct smbXsrv_connection *conn,
 	uint64_t local_zeros = volatile_id & 0xFFFFFFFF00000000LLU;
 	uint32_t global_id = persistent_id & UINT32_MAX;
 	uint64_t global_zeros = persistent_id & 0xFFFFFFFF00000000LLU;
+	NTSTATUS status;
 
 	if (local_zeros != 0) {
 		return NT_STATUS_FILE_CLOSED;
@@ -1170,7 +1263,65 @@ NTSTATUS smb2srv_open_lookup(struct smbXsrv_connection *conn,
 		return NT_STATUS_FILE_CLOSED;
 	}
 
-	return smbXsrv_open_local_lookup(table, local_id, global_id, now, _open);
+	status = smbXsrv_open_local_lookup(table, local_id, global_id, now,
+					   _open);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	/*
+	 * Clear the replay cache for this create_guid if it exists:
+	 * This is based on the assumption that this lookup will be
+	 * triggered by a client request using the file-id for lookup.
+	 * Hence the client has proven that it has in fact seen the
+	 * reply to its initial create call. So subsequent create replays
+	 * should be treated as invalid. Hence the index for create_guid
+	 * lookup needs to be removed.
+	 */
+	status = smbXsrv_open_clear_replay_cache(*_open);
+
+	return status;
+}
+
+NTSTATUS smb2srv_open_lookup_replay_cache(struct smbXsrv_connection *conn,
+					  const struct GUID *create_guid,
+					  NTTIME now, /* TODO: needed ? */
+					  struct smbXsrv_open **_open)
+{
+	NTSTATUS status;
+	char *guid_string;
+	struct GUID_txt_buf buf;
+	uint32_t local_id = 0;
+	struct smbXsrv_open_table *table = conn->client->open_table;
+	struct db_context *db = table->local.replay_cache_db_ctx;
+
+	if (GUID_all_zero(create_guid)) {
+		return NT_STATUS_NOT_FOUND;
+	}
+
+	guid_string = GUID_buf_string(create_guid, &buf);
+	if (guid_string == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	status = dbwrap_fetch_uint32_bystring(db, guid_string, &local_id);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+		return status;
+	}
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("failed to fetch local_id from replay cache: %s\n",
+			nt_errstr(status));
+		return status;
+	}
+
+	status = smbXsrv_open_local_lookup(table, local_id, 0, /* global_id */
+					   now, _open);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("smbXsrv_open_local_lookup failed for local_id %u\n",
+			(unsigned)local_id);
+	}
+
+	return status;
 }
 
 NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn,
diff --git a/source4/heimdal/lib/asn1/gen.c b/source4/heimdal/lib/asn1/gen.c
index 2194b32..fd833db 100644
--- a/source4/heimdal/lib/asn1/gen.c
+++ b/source4/heimdal/lib/asn1/gen.c
@@ -290,9 +290,10 @@ close_generate (void)
         fclose (privheaderfile);
     if (templatefile)
         fclose (templatefile);
-    if (logfile)
+    if (logfile) {
         fprintf (logfile, "\n");
         fclose (logfile);
+    }
 }
 
 void
diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c
index 6df8e50..56f38e7 100644
--- a/source4/lib/registry/tools/regtree.c
+++ b/source4/lib/registry/tools/regtree.c
@@ -46,7 +46,8 @@ static void print_tree(unsigned int level, struct registry_key *p,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list