The Samba-Bugzilla – Attachment 11904 Details for
Bug 11779
backports of SMB3 multichannel patches
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch from master
4-4-0-multichannel.patch (text/plain), 129.29 KB, created by
Guenther Deschner
on 2016-03-08 14:02:31 UTC
(
hide
)
Description:
patch from master
Filename:
MIME Type:
Creator:
Guenther Deschner
Created:
2016-03-08 14:02:31 UTC
Size:
129.29 KB
patch
obsolete
>From c70da3a0fba246bedbb7aa49bf448db4352e2c9f Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Fri, 15 Jan 2016 18:07:31 +0100 >Subject: [PATCH 01/40] s4-torture: let smb2.replay.replay2 test deal with > scale out shares. > >Guenther > >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/replay.c | 28 +++++++++++++++++++++------- > 1 file changed, 21 insertions(+), 7 deletions(-) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 57b14f1..83d36a3 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -302,12 +302,17 @@ static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) > bool ret = true; > const char *fname = BASEDIR "\\replay2.dat"; > struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; > > if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { > torture_skip(tctx, "SMB 3.X Dialect family required for " > "replay tests\n"); > } > >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ > ZERO_STRUCT(break_info); > break_info.tctx = tctx; > tree->session->transport->oplock.handler = torture_oplock_ack_handler; >@@ -336,10 +341,16 @@ static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) > _h = io.out.file.handle; > h = &_h; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); > CHECK_VAL(io.out.durable_open, false); >- CHECK_VAL(io.out.durable_open_v2, true); >- CHECK_VAL(io.out.timeout, io.in.timeout); >+ if (share_is_so) { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s")); >+ CHECK_VAL(io.out.durable_open_v2, false); >+ CHECK_VAL(io.out.timeout, 0); >+ } else { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ CHECK_VAL(io.out.timeout, io.in.timeout); >+ } > > /* > * Replay Durable V2 Create on single channel >@@ -392,10 +403,13 @@ static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) > io.in.durable_open_v2 = false; > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); >- CHECK_VAL(break_info.count, 1); >- CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle); >- CHECK_VAL(break_info.level, smb2_util_oplock_level("s")); >- ZERO_STRUCT(break_info); >+ >+ if (!share_is_so) { >+ CHECK_VAL(break_info.count, 1); >+ CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle); >+ CHECK_VAL(break_info.level, smb2_util_oplock_level("s")); >+ ZERO_STRUCT(break_info); >+ } > > smb2_util_close(tree, *h); > h = NULL; >-- >2.5.0 > > >From 884d04b941c08f261028a857b1b51168d068b8c5 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Fri, 15 Jan 2016 18:24:08 +0100 >Subject: [PATCH 02/40] s4-torture: let smb2.replay.replay3 test deal with > scale out shares. > >Guenther > >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/replay.c | 29 +++++++++++++++++++++++------ > 1 file changed, 23 insertions(+), 6 deletions(-) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 83d36a3..f045e17 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -485,12 +485,17 @@ static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) > struct smb2_transport *transport2 = NULL; > struct smb2_session *session1_1 = tree1->session; > struct smb2_session *session1_2 = NULL; >+ uint32_t share_capabilities; >+ bool share_is_so; > > if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) { > torture_skip(tctx, "SMB 3.X Dialect family required for " > "Replay tests\n"); > } > >+ share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ > ZERO_STRUCT(break_info); > break_info.tctx = tctx; > transport1->oplock.handler = torture_oplock_ack_handler; >@@ -522,10 +527,16 @@ static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) > _h = io.out.file.handle; > h = &_h; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ if (share_is_so) { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s")); >+ CHECK_VAL(io.out.durable_open_v2, false); >+ CHECK_VAL(io.out.timeout, 0); >+ } else { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ CHECK_VAL(io.out.timeout, io.in.timeout); >+ } > CHECK_VAL(io.out.durable_open, false); >- CHECK_VAL(io.out.durable_open_v2, true); >- CHECK_VAL(io.out.timeout, io.in.timeout); > CHECK_VAL(break_info.count, 0); > > status = smb2_connect(tctx, >@@ -571,10 +582,16 @@ static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) > _h = io.out.file.handle; > h = &_h; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ if (share_is_so) { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s")); >+ CHECK_VAL(io.out.durable_open_v2, false); >+ CHECK_VAL(io.out.timeout, 0); >+ } else { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ CHECK_VAL(io.out.timeout, io.in.timeout); >+ } > CHECK_VAL(io.out.durable_open, false); >- CHECK_VAL(io.out.durable_open_v2, true); >- CHECK_VAL(io.out.timeout, io.in.timeout); > CHECK_VAL(break_info.count, 0); > > tree1->session = session1_1; >-- >2.5.0 > > >From d134d40ff346a884baa3d780e0d07bd86933ace0 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Fri, 15 Jan 2016 18:30:15 +0100 >Subject: [PATCH 03/40] s4-torture: let smb2.replay.replay4 test deal with > scale out shares. > >Guenther > >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/replay.c | 23 +++++++++++++++++++---- > 1 file changed, 19 insertions(+), 4 deletions(-) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index f045e17..4b3f569 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -640,12 +640,17 @@ static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1) > struct smb2_session *session1_1 = tree1->session; > struct smb2_session *session1_2 = NULL; > uint16_t curr_cs; >+ uint32_t share_capabilities; >+ bool share_is_so; > > if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) { > torture_skip(tctx, "SMB 3.X Dialect family required for " > "Replay tests\n"); > } > >+ share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ > ZERO_STRUCT(break_info); > break_info.tctx = tctx; > transport1->oplock.handler = torture_oplock_ack_handler; >@@ -677,10 +682,16 @@ static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1) > _h1 = io.out.file.handle; > h1 = &_h1; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ if (share_is_so) { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s")); >+ CHECK_VAL(io.out.durable_open_v2, false); >+ CHECK_VAL(io.out.timeout, 0); >+ } else { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ CHECK_VAL(io.out.timeout, io.in.timeout); >+ } > CHECK_VAL(io.out.durable_open, false); >- CHECK_VAL(io.out.durable_open_v2, true); >- CHECK_VAL(io.out.timeout, io.in.timeout); > CHECK_VAL(break_info.count, 0); > > status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf)); >@@ -821,7 +832,11 @@ static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1) > smb2_util_close(tree1, *h1); > h1 = NULL; > >- CHECK_VAL(break_info.count, 0); >+ if (share_is_so) { >+ CHECK_VAL(break_info.count, 1); >+ } else { >+ CHECK_VAL(break_info.count, 0); >+ } > done: > talloc_free(tree2); > tree1->session = session1_1; >-- >2.5.0 > > >From 15bafd790990774edf0fd81aaaabab142a99f24c Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 22 Feb 2016 14:32:44 +0100 >Subject: [PATCH 04/40] torture:smb2: rewrite connect test to use > torture_asserts > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/connect.c | 63 ++++++++++++++---------------------------- > 1 file changed, 20 insertions(+), 43 deletions(-) > >diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c >index 0067de0..6fd331a 100644 >--- a/source4/torture/smb2/connect.c >+++ b/source4/torture/smb2/connect.c >@@ -194,74 +194,51 @@ bool torture_smb2_connect(struct torture_context *torture) > struct smb2_request *req; > struct smb2_handle h1, h2; > NTSTATUS status; >+ bool ok; > >- if (!torture_smb2_connection(torture, &tree)) { >- return false; >- } >+ ok = torture_smb2_connection(torture, &tree); >+ torture_assert(torture, ok, "torture_smb2_connection failed"); > > smb2_util_unlink(tree, "test9.dat"); > > h1 = torture_smb2_createfile(tree, "test9.dat"); > h2 = torture_smb2_createfile(tree, "test9.dat"); >+ > status = torture_smb2_write(torture, tree, h1); >- if (!NT_STATUS_IS_OK(status)) { >- printf("Write failed - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_ok(torture, status, "write failed"); >+ > status = torture_smb2_close(tree, h1); >- if (!NT_STATUS_IS_OK(status)) { >- printf("Close failed - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_ok(torture, status, "close failed"); >+ > status = torture_smb2_close(tree, h2); >- if (!NT_STATUS_IS_OK(status)) { >- printf("Close failed - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_ok(torture, status, "close failed"); > > status = smb2_util_close(tree, h1); >- if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) { >- printf("close should have closed the handle - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_equal(torture, status, NT_STATUS_FILE_CLOSED, >+ "close should have closed the handle"); > > status = smb2_tdis(tree); >- if (!NT_STATUS_IS_OK(status)) { >- printf("tdis failed - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_ok(torture, status, "tdis failed"); > > status = smb2_tdis(tree); >- if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) { >- printf("tdis should have disabled session - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_equal(torture, status, >+ NT_STATUS_NETWORK_NAME_DELETED, >+ "tdis should have closed the tcon"); > > status = smb2_logoff(tree->session); >- if (!NT_STATUS_IS_OK(status)) { >- printf("Logoff failed - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_ok(torture, status, "logoff failed"); > > req = smb2_logoff_send(tree->session); >- if (!req) { >- printf("smb2_logoff_send() failed\n"); >- return false; >- } >+ torture_assert_not_null(torture, req, "smb2_logoff_send failed"); > > req->session = NULL; > > status = smb2_logoff_recv(req); >- if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) { >- printf("Logoff should have disabled session - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_equal(torture, status, NT_STATUS_USER_SESSION_DELETED, >+ "logoff should have disabled session"); > > status = smb2_keepalive(tree->session->transport); >- if (!NT_STATUS_IS_OK(status)) { >- printf("keepalive failed? - %s\n", nt_errstr(status)); >- return false; >- } >+ torture_assert_ntstatus_ok(torture, status, "keepalive failed"); > > talloc_free(mem_ctx); > >-- >2.5.0 > > >From c4c70b038913ae988ccda1aa26d4d772d85aec5c Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 22 Feb 2016 16:22:14 +0100 >Subject: [PATCH 05/40] torture:smb2: rewrite connect test to use > torture_asserts for create errors > >let torture_smb2_createfile propagate errors > >Signed-off-by: Michael Adam <obnox@samba.org> >--- > source4/torture/smb2/connect.c | 21 +++++++++++++-------- > 1 file changed, 13 insertions(+), 8 deletions(-) > >diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c >index 6fd331a..f68c34f 100644 >--- a/source4/torture/smb2/connect.c >+++ b/source4/torture/smb2/connect.c >@@ -137,8 +137,9 @@ static NTSTATUS torture_smb2_write(struct torture_context *tctx, struct smb2_tre > /* > send a create > */ >-static struct smb2_handle torture_smb2_createfile(struct smb2_tree *tree, >- const char *fname) >+static NTSTATUS torture_smb2_createfile(struct smb2_tree *tree, >+ const char *fname, >+ struct smb2_handle *handle) > { > struct smb2_create io; > NTSTATUS status; >@@ -158,8 +159,7 @@ static struct smb2_handle torture_smb2_createfile(struct smb2_tree *tree, > > status = smb2_create(tree, tmp_ctx, &io); > if (!NT_STATUS_IS_OK(status)) { >- printf("create1 failed - %s\n", nt_errstr(status)); >- return io.out.file.handle; >+ return status; > } > > if (DEBUGLVL(1)) { >@@ -179,8 +179,10 @@ static struct smb2_handle torture_smb2_createfile(struct smb2_tree *tree, > } > > talloc_free(tmp_ctx); >- >- return io.out.file.handle; >+ >+ *handle = io.out.file.handle; >+ >+ return NT_STATUS_OK; > } > > >@@ -201,8 +203,11 @@ bool torture_smb2_connect(struct torture_context *torture) > > smb2_util_unlink(tree, "test9.dat"); > >- h1 = torture_smb2_createfile(tree, "test9.dat"); >- h2 = torture_smb2_createfile(tree, "test9.dat"); >+ status = torture_smb2_createfile(tree, "test9.dat", &h1); >+ torture_assert_ntstatus_ok(torture, status, "create failed"); >+ >+ status = torture_smb2_createfile(tree, "test9.dat", &h2); >+ torture_assert_ntstatus_ok(torture, status, "create failed"); > > status = torture_smb2_write(torture, tree, h1); > torture_assert_ntstatus_ok(torture, status, "write failed"); >-- >2.5.0 > > >From 88d25932f65bc33f79c42ba2afee4ebe5a5c8354 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 22 Feb 2016 23:23:13 +0100 >Subject: [PATCH 06/40] torture:smb2: fix memory leak in connect test. > >Signed-off-by: Michael Adam <obnox@samba.org> >--- > source4/torture/smb2/connect.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c >index f68c34f..e3716be 100644 >--- a/source4/torture/smb2/connect.c >+++ b/source4/torture/smb2/connect.c >@@ -159,6 +159,7 @@ static NTSTATUS torture_smb2_createfile(struct smb2_tree *tree, > > status = smb2_create(tree, tmp_ctx, &io); > if (!NT_STATUS_IS_OK(status)) { >+ TALLOC_FREE(tmp_ctx); > return status; > } > >-- >2.5.0 > > >From 2d7db94a1e26900b526b5bac3e23d68c31d2b39c Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 23 Feb 2016 00:27:11 +0100 >Subject: [PATCH 07/40] torture:smb2: improve torture_comments in connect test > >Signed-off-by: Michael Adam <obnox@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Tue Feb 23 04:50:53 CET 2016 on sn-devel-144 >--- > source4/torture/smb2/connect.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > >diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c >index e3716be..6340430 100644 >--- a/source4/torture/smb2/connect.c >+++ b/source4/torture/smb2/connect.c >@@ -90,7 +90,7 @@ static NTSTATUS torture_smb2_write(struct torture_context *tctx, struct smb2_tre > > status = smb2_write(tree, &w); > if (!NT_STATUS_IS_OK(status)) { >- printf("write failed - %s\n", nt_errstr(status)); >+ printf("write 1 failed - %s\n", nt_errstr(status)); > return status; > } > >@@ -98,7 +98,7 @@ static NTSTATUS torture_smb2_write(struct torture_context *tctx, struct smb2_tre > > status = smb2_write(tree, &w); > if (!NT_STATUS_IS_OK(status)) { >- printf("write failed - %s\n", nt_errstr(status)); >+ printf("write 2 failed - %s\n", nt_errstr(status)); > return status; > } > >-- >2.5.0 > > >From 5196d6ec3e0c04ce7a50f966b7409f49f696e365 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Fri, 26 Feb 2016 00:41:24 +0100 >Subject: [PATCH 08/40] smbXsrv_open: factor fetch-locking of global record > into function > >smbXsrv_open_global_fetch_locked() > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smbXsrv_open.c | 85 +++++++++++++++++++-------------------------- > 1 file changed, 36 insertions(+), 49 deletions(-) > >diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index 1fe8b1b..737b2b9 100644 >--- a/source3/smbd/smbXsrv_open.c >+++ b/source3/smbd/smbXsrv_open.c >@@ -151,6 +151,27 @@ static NTSTATUS smbXsrv_open_local_key_to_id(TDB_DATA key, uint32_t *id) > return NT_STATUS_OK; > } > >+static struct db_record *smbXsrv_open_global_fetch_locked( >+ struct db_context *db, >+ uint32_t id, >+ TALLOC_CTX *mem_ctx) >+{ >+ TDB_DATA key; >+ uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; >+ struct db_record *rec = NULL; >+ >+ key = smbXsrv_open_global_id_to_key(id, key_buf); >+ >+ rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ >+ if (rec == NULL) { >+ DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id, >+ hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); >+ } >+ >+ return rec; >+} >+ > static NTSTATUS smbXsrv_open_table_init(struct smbXsrv_connection *conn, > uint32_t lowest_id, > uint32_t highest_id, >@@ -494,8 +515,6 @@ static NTSTATUS smbXsrv_open_global_allocate(struct db_context *db, > bool is_free = false; > bool was_free = false; > uint32_t id; >- uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (i >= min_tries && last_free != 0) { > id = last_free; >@@ -509,9 +528,7 @@ static NTSTATUS smbXsrv_open_global_allocate(struct db_context *db, > id--; > } > >- key = smbXsrv_open_global_id_to_key(id, key_buf); >- >- global->db_rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ global->db_rec = smbXsrv_open_global_fetch_locked(db, id, mem_ctx); > if (global->db_rec == NULL) { > talloc_free(global); > return NT_STATUS_INSUFFICIENT_RESOURCES; >@@ -717,8 +734,6 @@ static NTSTATUS smbXsrv_open_global_lookup(struct smbXsrv_open_table *table, > TALLOC_CTX *mem_ctx, > struct smbXsrv_open_global0 **_global) > { >- TDB_DATA key; >- uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; > struct db_record *global_rec = NULL; > bool is_free = false; > >@@ -728,15 +743,10 @@ static NTSTATUS smbXsrv_open_global_lookup(struct smbXsrv_open_table *table, > return NT_STATUS_INTERNAL_ERROR; > } > >- key = smbXsrv_open_global_id_to_key(open_global_id, key_buf); >- >- global_rec = dbwrap_fetch_locked(table->global.db_ctx, mem_ctx, key); >+ global_rec = smbXsrv_open_global_fetch_locked(table->global.db_ctx, >+ open_global_id, >+ mem_ctx); > if (global_rec == NULL) { >- DEBUG(0, ("smbXsrv_open_global_lookup(0x%08x): " >- "Failed to lock global key '%s'\n", >- open_global_id, >- hex_encode_talloc(talloc_tos(), key.dptr, >- key.dsize))); > return NT_STATUS_INTERNAL_DB_ERROR; > } > >@@ -909,8 +919,6 @@ NTSTATUS smbXsrv_open_update(struct smbXsrv_open *op) > { > struct smbXsrv_open_table *table = op->table; > NTSTATUS status; >- uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (op->global->db_rec != NULL) { > DEBUG(0, ("smbXsrv_open_update(0x%08x): " >@@ -919,17 +927,11 @@ NTSTATUS smbXsrv_open_update(struct smbXsrv_open *op) > return NT_STATUS_INTERNAL_ERROR; > } > >- key = smbXsrv_open_global_id_to_key(op->global->open_global_id, >- key_buf); >- >- op->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx, >- op->global, key); >+ op->global->db_rec = smbXsrv_open_global_fetch_locked( >+ table->global.db_ctx, >+ op->global->open_global_id, >+ op->global /* TALLOC_CTX */); > if (op->global->db_rec == NULL) { >- DEBUG(0, ("smbXsrv_open_update(0x%08x): " >- "Failed to lock global key '%s'\n", >- op->global->open_global_id, >- hex_encode_talloc(talloc_tos(), key.dptr, >- key.dsize))); > return NT_STATUS_INTERNAL_DB_ERROR; > } > >@@ -979,21 +981,11 @@ NTSTATUS smbXsrv_open_close(struct smbXsrv_open *op, NTTIME now) > global_rec = op->global->db_rec; > op->global->db_rec = NULL; > if (global_rec == NULL) { >- uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; >- >- key = smbXsrv_open_global_id_to_key( >- op->global->open_global_id, >- key_buf); >- >- global_rec = dbwrap_fetch_locked(table->global.db_ctx, >- op->global, key); >+ global_rec = smbXsrv_open_global_fetch_locked( >+ table->global.db_ctx, >+ op->global->open_global_id, >+ op->global /* TALLOC_CTX */); > if (global_rec == NULL) { >- DEBUG(0, ("smbXsrv_open_close(0x%08x): " >- "Failed to lock global key '%s'\n", >- op->global->open_global_id, >- hex_encode_talloc(global_rec, key.dptr, >- key.dsize))); > error = NT_STATUS_INTERNAL_ERROR; > } > } >@@ -1403,21 +1395,16 @@ NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) > NTSTATUS status = NT_STATUS_OK; > TALLOC_CTX *frame = talloc_stackframe(); > struct smbXsrv_open_global0 *op = NULL; >- uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > TDB_DATA val; > struct db_record *rec; > bool delete_open = false; > uint32_t global_id = persistent_id & UINT32_MAX; > >- key = smbXsrv_open_global_id_to_key(global_id, key_buf); >- rec = dbwrap_fetch_locked(smbXsrv_open_global_db_ctx, frame, key); >+ rec = smbXsrv_open_global_fetch_locked(smbXsrv_open_global_db_ctx, >+ global_id, >+ frame); > if (rec == NULL) { > status = NT_STATUS_NOT_FOUND; >- DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " >- "failed to fetch record from %s - %s\n", >- global_id, dbwrap_name(smbXsrv_open_global_db_ctx), >- nt_errstr(status))); > goto done; > } > >-- >2.5.0 > > >From 17fa947e108f63152d464e25cd81e6710eeba28b Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Fri, 26 Feb 2016 00:53:22 +0100 >Subject: [PATCH 09/40] smbXsrv_open: factor fetch-locking of local record into > function > >smbXsrv_open_local_fetch_locked() > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Fri Feb 26 22:35:28 CET 2016 on sn-devel-144 >--- > source3/smbd/smbXsrv_open.c | 48 ++++++++++++++++++++++++--------------------- > 1 file changed, 26 insertions(+), 22 deletions(-) > >diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index 737b2b9..ee35f2d 100644 >--- a/source3/smbd/smbXsrv_open.c >+++ b/source3/smbd/smbXsrv_open.c >@@ -172,6 +172,27 @@ static struct db_record *smbXsrv_open_global_fetch_locked( > return rec; > } > >+static struct db_record *smbXsrv_open_local_fetch_locked( >+ struct db_context *db, >+ uint32_t id, >+ TALLOC_CTX *mem_ctx) >+{ >+ TDB_DATA key; >+ uint8_t key_buf[SMBXSRV_OPEN_LOCAL_TDB_KEY_SIZE]; >+ struct db_record *rec = NULL; >+ >+ key = smbXsrv_open_local_id_to_key(id, key_buf); >+ >+ rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ >+ if (rec == NULL) { >+ DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id, >+ hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); >+ } >+ >+ return rec; >+} >+ > static NTSTATUS smbXsrv_open_table_init(struct smbXsrv_connection *conn, > uint32_t lowest_id, > uint32_t highest_id, >@@ -296,8 +317,6 @@ static NTSTATUS smbXsrv_open_local_allocate_id(struct db_context *db, > > for (i = 0; i < (range / 2); i++) { > uint32_t id; >- uint8_t key_buf[SMBXSRV_OPEN_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > TDB_DATA val; > struct db_record *rec = NULL; > >@@ -311,9 +330,7 @@ static NTSTATUS smbXsrv_open_local_allocate_id(struct db_context *db, > id = highest_id; > } > >- key = smbXsrv_open_local_id_to_key(id, key_buf); >- >- rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ rec = smbXsrv_open_local_fetch_locked(db, id, mem_ctx); > if (rec == NULL) { > return NT_STATUS_INSUFFICIENT_RESOURCES; > } >@@ -363,16 +380,12 @@ static NTSTATUS smbXsrv_open_local_allocate_id(struct db_context *db, > > if (NT_STATUS_IS_OK(state.status)) { > uint32_t id; >- uint8_t key_buf[SMBXSRV_OPEN_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > TDB_DATA val; > struct db_record *rec = NULL; > > id = state.useable_id; > >- key = smbXsrv_open_local_id_to_key(id, key_buf); >- >- rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ rec = smbXsrv_open_local_fetch_locked(db, id, mem_ctx); > if (rec == NULL) { > return NT_STATUS_INSUFFICIENT_RESOURCES; > } >@@ -1044,19 +1057,10 @@ NTSTATUS smbXsrv_open_close(struct smbXsrv_open *op, NTTIME now) > > local_rec = op->db_rec; > if (local_rec == NULL) { >- uint8_t key_buf[SMBXSRV_OPEN_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; >- >- key = smbXsrv_open_local_id_to_key(op->local_id, key_buf); >- >- local_rec = dbwrap_fetch_locked(table->local.db_ctx, >- op, key); >+ local_rec = smbXsrv_open_local_fetch_locked(table->local.db_ctx, >+ op->local_id, >+ op /* TALLOC_CTX*/); > if (local_rec == NULL) { >- DEBUG(0, ("smbXsrv_open_close(0x%08x): " >- "Failed to lock local key '%s'\n", >- op->global->open_global_id, >- hex_encode_talloc(local_rec, key.dptr, >- key.dsize))); > error = NT_STATUS_INTERNAL_ERROR; > } > } >-- >2.5.0 > > >From 58007fc7c2ca8cb56d7fd1d4a3aedffa43d7a358 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sat, 27 Feb 2016 00:52:59 +0100 >Subject: [PATCH 10/40] smbXsrv_tcon: factor fetch-locking of global record > into function > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smbXsrv_tcon.c | 61 ++++++++++++++++++++++----------------------- > 1 file changed, 30 insertions(+), 31 deletions(-) > >diff --git a/source3/smbd/smbXsrv_tcon.c b/source3/smbd/smbXsrv_tcon.c >index 1d2a141..5f10c49 100644 >--- a/source3/smbd/smbXsrv_tcon.c >+++ b/source3/smbd/smbXsrv_tcon.c >@@ -150,6 +150,27 @@ static NTSTATUS smbXsrv_tcon_local_key_to_id(TDB_DATA key, uint32_t *id) > return NT_STATUS_OK; > } > >+static struct db_record *smbXsrv_tcon_global_fetch_locked( >+ struct db_context *db, >+ uint32_t id, >+ TALLOC_CTX *mem_ctx) >+{ >+ TDB_DATA key; >+ uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE]; >+ struct db_record *rec = NULL; >+ >+ key = smbXsrv_tcon_global_id_to_key(id, key_buf); >+ >+ rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ >+ if (rec == NULL) { >+ DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id, >+ hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); >+ } >+ >+ return rec; >+} >+ > static NTSTATUS smbXsrv_tcon_table_init(TALLOC_CTX *mem_ctx, > struct smbXsrv_tcon_table *table, > uint32_t lowest_id, >@@ -473,8 +494,6 @@ static NTSTATUS smbXsrv_tcon_global_allocate(struct db_context *db, > bool is_free = false; > bool was_free = false; > uint32_t id; >- uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (i >= min_tries && last_free != 0) { > id = last_free; >@@ -488,9 +507,8 @@ static NTSTATUS smbXsrv_tcon_global_allocate(struct db_context *db, > id--; > } > >- key = smbXsrv_tcon_global_id_to_key(id, key_buf); >- >- global->db_rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ global->db_rec = smbXsrv_tcon_global_fetch_locked(db, id, >+ mem_ctx); > if (global->db_rec == NULL) { > talloc_free(global); > return NT_STATUS_INSUFFICIENT_RESOURCES; >@@ -820,8 +838,6 @@ NTSTATUS smbXsrv_tcon_update(struct smbXsrv_tcon *tcon) > { > struct smbXsrv_tcon_table *table = tcon->table; > NTSTATUS status; >- uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (tcon->global->db_rec != NULL) { > DEBUG(0, ("smbXsrv_tcon_update(0x%08x): " >@@ -830,17 +846,11 @@ NTSTATUS smbXsrv_tcon_update(struct smbXsrv_tcon *tcon) > return NT_STATUS_INTERNAL_ERROR; > } > >- key = smbXsrv_tcon_global_id_to_key(tcon->global->tcon_global_id, >- key_buf); >- >- tcon->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx, >- tcon->global, key); >+ tcon->global->db_rec = smbXsrv_tcon_global_fetch_locked( >+ table->global.db_ctx, >+ tcon->global->tcon_global_id, >+ tcon->global /* TALLOC_CTX */); > if (tcon->global->db_rec == NULL) { >- DEBUG(0, ("smbXsrv_tcon_update(0x%08x): " >- "Failed to lock global key '%s'\n", >- tcon->global->tcon_global_id, >- hex_encode_talloc(talloc_tos(), key.dptr, >- key.dsize))); > return NT_STATUS_INTERNAL_DB_ERROR; > } > >@@ -888,22 +898,11 @@ NTSTATUS smbXsrv_tcon_disconnect(struct smbXsrv_tcon *tcon, uint64_t vuid) > global_rec = tcon->global->db_rec; > tcon->global->db_rec = NULL; > if (global_rec == NULL) { >- uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; >- >- key = smbXsrv_tcon_global_id_to_key( >+ global_rec = smbXsrv_tcon_global_fetch_locked( >+ table->global.db_ctx, > tcon->global->tcon_global_id, >- key_buf); >- >- global_rec = dbwrap_fetch_locked(table->global.db_ctx, >- tcon->global, key); >+ tcon->global /* TALLOC_CTX */); > if (global_rec == NULL) { >- DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): " >- "Failed to lock global key '%s'\n", >- tcon->global->tcon_global_id, >- tcon->global->share_name, >- hex_encode_talloc(global_rec, key.dptr, >- key.dsize))); > error = NT_STATUS_INTERNAL_ERROR; > } > } >-- >2.5.0 > > >From b91b26247900fdb752cecb63ab729cdc4b7da6dd Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sat, 27 Feb 2016 01:06:13 +0100 >Subject: [PATCH 11/40] smbXsrv_tcon: factor fetch-locking of local record into > function > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smbXsrv_tcon.c | 58 ++++++++++++++++++++++----------------------- > 1 file changed, 29 insertions(+), 29 deletions(-) > >diff --git a/source3/smbd/smbXsrv_tcon.c b/source3/smbd/smbXsrv_tcon.c >index 5f10c49..ddd03f6 100644 >--- a/source3/smbd/smbXsrv_tcon.c >+++ b/source3/smbd/smbXsrv_tcon.c >@@ -171,6 +171,27 @@ static struct db_record *smbXsrv_tcon_global_fetch_locked( > return rec; > } > >+static struct db_record *smbXsrv_tcon_local_fetch_locked( >+ struct db_context *db, >+ uint32_t id, >+ TALLOC_CTX *mem_ctx) >+{ >+ TDB_DATA key; >+ uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE]; >+ struct db_record *rec = NULL; >+ >+ key = smbXsrv_tcon_local_id_to_key(id, key_buf); >+ >+ rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ >+ if (rec == NULL) { >+ DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id, >+ hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); >+ } >+ >+ return rec; >+} >+ > static NTSTATUS smbXsrv_tcon_table_init(TALLOC_CTX *mem_ctx, > struct smbXsrv_tcon_table *table, > uint32_t lowest_id, >@@ -287,8 +308,6 @@ static NTSTATUS smb1srv_tcon_local_allocate_id(struct db_context *db, > > for (i = 0; i < (range / 2); i++) { > uint32_t id; >- uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > TDB_DATA val; > struct db_record *rec = NULL; > >@@ -302,9 +321,7 @@ static NTSTATUS smb1srv_tcon_local_allocate_id(struct db_context *db, > id = highest_id; > } > >- key = smbXsrv_tcon_local_id_to_key(id, key_buf); >- >- rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ rec = smbXsrv_tcon_local_fetch_locked(db, id, mem_ctx); > if (rec == NULL) { > return NT_STATUS_INSUFFICIENT_RESOURCES; > } >@@ -354,16 +371,12 @@ static NTSTATUS smb1srv_tcon_local_allocate_id(struct db_context *db, > > if (NT_STATUS_IS_OK(state.status)) { > uint32_t id; >- uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > TDB_DATA val; > struct db_record *rec = NULL; > > id = state.useable_id; > >- key = smbXsrv_tcon_local_id_to_key(id, key_buf); >- >- rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ rec = smbXsrv_tcon_local_fetch_locked(db, id, mem_ctx); > if (rec == NULL) { > return NT_STATUS_INSUFFICIENT_RESOURCES; > } >@@ -755,17 +768,14 @@ static NTSTATUS smbXsrv_tcon_create(struct smbXsrv_tcon_table *table, > > if (protocol >= PROTOCOL_SMB2_02) { > uint64_t id = global->tcon_global_id; >- uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > global->tcon_wire_id = id; > > tcon->local_id = global->tcon_global_id; > >- key = smbXsrv_tcon_local_id_to_key(tcon->local_id, key_buf); >- >- local_rec = dbwrap_fetch_locked(table->local.db_ctx, >- tcon, key); >+ local_rec = smbXsrv_tcon_local_fetch_locked(table->local.db_ctx, >+ tcon->local_id, >+ tcon /* TALLOC_CTX */); > if (local_rec == NULL) { > TALLOC_FREE(tcon); > return NT_STATUS_NO_MEMORY; >@@ -926,20 +936,10 @@ NTSTATUS smbXsrv_tcon_disconnect(struct smbXsrv_tcon *tcon, uint64_t vuid) > > local_rec = tcon->db_rec; > if (local_rec == NULL) { >- uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; >- >- key = smbXsrv_tcon_local_id_to_key(tcon->local_id, key_buf); >- >- local_rec = dbwrap_fetch_locked(table->local.db_ctx, >- tcon, key); >+ local_rec = smbXsrv_tcon_local_fetch_locked(table->local.db_ctx, >+ tcon->local_id, >+ tcon /* TALLOC_CTX */); > if (local_rec == NULL) { >- DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): " >- "Failed to lock local key '%s'\n", >- tcon->global->tcon_global_id, >- tcon->global->share_name, >- hex_encode_talloc(local_rec, key.dptr, >- key.dsize))); > error = NT_STATUS_INTERNAL_ERROR; > } > } >-- >2.5.0 > > >From 61ac25c7deb9c0fdeea85259893a54e3e618741f Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sat, 27 Feb 2016 01:26:16 +0100 >Subject: [PATCH 12/40] smbXsrv_session: factor fetch-locking of global record > into function > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smbXsrv_session.c | 69 ++++++++++++++++++++---------------------- > 1 file changed, 33 insertions(+), 36 deletions(-) > >diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c >index 732388b..f7cc629 100644 >--- a/source3/smbd/smbXsrv_session.c >+++ b/source3/smbd/smbXsrv_session.c >@@ -161,6 +161,27 @@ static NTSTATUS smbXsrv_session_local_key_to_id(TDB_DATA key, uint32_t *id) > return NT_STATUS_OK; > } > >+static struct db_record *smbXsrv_session_global_fetch_locked( >+ struct db_context *db, >+ uint32_t id, >+ TALLOC_CTX *mem_ctx) >+{ >+ TDB_DATA key; >+ uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE]; >+ struct db_record *rec = NULL; >+ >+ key = smbXsrv_session_global_id_to_key(id, key_buf); >+ >+ rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ >+ if (rec == NULL) { >+ DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id, >+ hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); >+ } >+ >+ return rec; >+} >+ > static void smbXsrv_session_close_loop(struct tevent_req *subreq); > > static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn, >@@ -693,8 +714,6 @@ static NTSTATUS smbXsrv_session_global_allocate(struct db_context *db, > bool is_free = false; > bool was_free = false; > uint32_t id; >- uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (i >= min_tries && last_free != 0) { > id = last_free; >@@ -708,9 +727,8 @@ static NTSTATUS smbXsrv_session_global_allocate(struct db_context *db, > id--; > } > >- key = smbXsrv_session_global_id_to_key(id, key_buf); >- >- global->db_rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ global->db_rec = smbXsrv_session_global_fetch_locked(db, id, >+ mem_ctx); > if (global->db_rec == NULL) { > talloc_free(global); > return NT_STATUS_INSUFFICIENT_RESOURCES; >@@ -931,8 +949,6 @@ struct tevent_req *smb2srv_session_close_previous_send(TALLOC_CTX *mem_ctx, > uint64_t global_zeros = previous_session_id & 0xFFFFFFFF00000000LLU; > struct smbXsrv_session_table *table = conn->client->session_table; > struct security_token *current_token = NULL; >- uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > req = tevent_req_create(mem_ctx, &state, > struct smb2srv_session_close_previous_state); >@@ -969,10 +985,10 @@ struct tevent_req *smb2srv_session_close_previous_send(TALLOC_CTX *mem_ctx, > return tevent_req_post(req, ev); > } > >- key = smbXsrv_session_global_id_to_key(global_id, key_buf); >- >- state->db_rec = dbwrap_fetch_locked(table->global.db_ctx, >- state, key); >+ state->db_rec = smbXsrv_session_global_fetch_locked( >+ table->global.db_ctx, >+ global_id, >+ state /* TALLOC_CTX */); > if (state->db_rec == NULL) { > tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); > return tevent_req_post(req, ev); >@@ -1336,8 +1352,6 @@ NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session) > { > struct smbXsrv_session_table *table = session->table; > NTSTATUS status; >- uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (session->global->db_rec != NULL) { > DEBUG(0, ("smbXsrv_session_update(0x%08x): " >@@ -1346,18 +1360,11 @@ NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session) > return NT_STATUS_INTERNAL_ERROR; > } > >- key = smbXsrv_session_global_id_to_key( >+ session->global->db_rec = smbXsrv_session_global_fetch_locked( >+ table->global.db_ctx, > session->global->session_global_id, >- key_buf); >- >- session->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx, >- session->global, key); >+ session->global /* TALLOC_CTX */); > if (session->global->db_rec == NULL) { >- DEBUG(0, ("smbXsrv_session_update(0x%08x): " >- "Failed to lock global key '%s'\n", >- session->global->session_global_id, >- hex_encode_talloc(talloc_tos(), key.dptr, >- key.dsize))); > return NT_STATUS_INTERNAL_DB_ERROR; > } > >@@ -1621,21 +1628,11 @@ NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session) > global_rec = session->global->db_rec; > session->global->db_rec = NULL; > if (global_rec == NULL) { >- uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; >- >- key = smbXsrv_session_global_id_to_key( >+ global_rec = smbXsrv_session_global_fetch_locked( >+ table->global.db_ctx, > session->global->session_global_id, >- key_buf); >- >- global_rec = dbwrap_fetch_locked(table->global.db_ctx, >- session->global, key); >+ session->global /* TALLOC_CTX */); > if (global_rec == NULL) { >- DEBUG(0, ("smbXsrv_session_logoff(0x%08x): " >- "Failed to lock global key '%s'\n", >- session->global->session_global_id, >- hex_encode_talloc(global_rec, key.dptr, >- key.dsize))); > error = NT_STATUS_INTERNAL_ERROR; > } > } >-- >2.5.0 > > >From deaf3389eb0575018ad5919d900330c40c558455 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sat, 27 Feb 2016 01:37:34 +0100 >Subject: [PATCH 13/40] smbXsrv_session: factor fetch-locking of local record > into function > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smbXsrv_session.c | 60 ++++++++++++++++++++++-------------------- > 1 file changed, 31 insertions(+), 29 deletions(-) > >diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c >index f7cc629..a5aee8c 100644 >--- a/source3/smbd/smbXsrv_session.c >+++ b/source3/smbd/smbXsrv_session.c >@@ -182,6 +182,27 @@ static struct db_record *smbXsrv_session_global_fetch_locked( > return rec; > } > >+static struct db_record *smbXsrv_session_local_fetch_locked( >+ struct db_context *db, >+ uint32_t id, >+ TALLOC_CTX *mem_ctx) >+{ >+ TDB_DATA key; >+ uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE]; >+ struct db_record *rec = NULL; >+ >+ key = smbXsrv_session_local_id_to_key(id, key_buf); >+ >+ rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ >+ if (rec == NULL) { >+ DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id, >+ hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); >+ } >+ >+ return rec; >+} >+ > static void smbXsrv_session_close_loop(struct tevent_req *subreq); > > static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn, >@@ -483,8 +504,6 @@ static NTSTATUS smb1srv_session_local_allocate_id(struct db_context *db, > > for (i = 0; i < (range / 2); i++) { > uint32_t id; >- uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > TDB_DATA val; > struct db_record *rec = NULL; > >@@ -498,9 +517,7 @@ static NTSTATUS smb1srv_session_local_allocate_id(struct db_context *db, > id = highest_id; > } > >- key = smbXsrv_session_local_id_to_key(id, key_buf); >- >- rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx); > if (rec == NULL) { > return NT_STATUS_INSUFFICIENT_RESOURCES; > } >@@ -550,16 +567,12 @@ static NTSTATUS smb1srv_session_local_allocate_id(struct db_context *db, > > if (NT_STATUS_IS_OK(state.status)) { > uint32_t id; >- uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > TDB_DATA val; > struct db_record *rec = NULL; > > id = state.useable_id; > >- key = smbXsrv_session_local_id_to_key(id, key_buf); >- >- rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx); > if (rec == NULL) { > return NT_STATUS_INSUFFICIENT_RESOURCES; > } >@@ -1206,8 +1219,6 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn, > > if (conn->protocol >= PROTOCOL_SMB2_02) { > uint64_t id = global->session_global_id; >- uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > global->connection_dialect = conn->smb2.server.dialect; > >@@ -1221,10 +1232,10 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn, > > session->local_id = global->session_global_id; > >- key = smbXsrv_session_local_id_to_key(session->local_id, key_buf); >- >- local_rec = dbwrap_fetch_locked(table->local.db_ctx, >- session, key); >+ local_rec = smbXsrv_session_local_fetch_locked( >+ table->local.db_ctx, >+ session->local_id, >+ session /* TALLOC_CTX */); > if (local_rec == NULL) { > TALLOC_FREE(session); > return NT_STATUS_NO_MEMORY; >@@ -1655,20 +1666,11 @@ NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session) > > local_rec = session->db_rec; > if (local_rec == NULL) { >- uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE]; >- TDB_DATA key; >- >- key = smbXsrv_session_local_id_to_key(session->local_id, >- key_buf); >- >- local_rec = dbwrap_fetch_locked(table->local.db_ctx, >- session, key); >+ local_rec = smbXsrv_session_local_fetch_locked( >+ table->local.db_ctx, >+ session->local_id, >+ session /* TALLOC_CTX */); > if (local_rec == NULL) { >- DEBUG(0, ("smbXsrv_session_logoff(0x%08x): " >- "Failed to lock local key '%s'\n", >- session->global->session_global_id, >- hex_encode_talloc(local_rec, key.dptr, >- key.dsize))); > error = NT_STATUS_INTERNAL_ERROR; > } > } >-- >2.5.0 > > >From 4bcd267dba16b58e62846bc6f8b53355f3aa2c86 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sat, 27 Feb 2016 01:58:45 +0100 >Subject: [PATCH 14/40] smbXsrv_client: factor fetch-locking of global record > into function > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smbXsrv_client.c | 62 +++++++++++++++++++++++-------------------- > 1 file changed, 33 insertions(+), 29 deletions(-) > >diff --git a/source3/smbd/smbXsrv_client.c b/source3/smbd/smbXsrv_client.c >index 0e21fc6..2dd4cad 100644 >--- a/source3/smbd/smbXsrv_client.c >+++ b/source3/smbd/smbXsrv_client.c >@@ -118,6 +118,28 @@ static TDB_DATA smbXsrv_client_global_id_to_key(const struct GUID *client_guid, > return key; > } > >+static struct db_record *smbXsrv_client_global_fetch_locked( >+ struct db_context *db, >+ const struct GUID *client_guid, >+ TALLOC_CTX *mem_ctx) >+{ >+ TDB_DATA key; >+ uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE]; >+ struct db_record *rec = NULL; >+ >+ key = smbXsrv_client_global_id_to_key(client_guid, key_buf); >+ >+ rec = dbwrap_fetch_locked(db, mem_ctx, key); >+ >+ if (rec == NULL) { >+ DBG_DEBUG("Failed to lock guid [%s], key '%s'\n", >+ GUID_string(talloc_tos(), client_guid), >+ hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); >+ } >+ >+ return rec; >+} >+ > static NTSTATUS smbXsrv_client_table_create(TALLOC_CTX *mem_ctx, > struct messaging_context *msg_ctx, > uint32_t max_clients, >@@ -252,18 +274,12 @@ NTSTATUS smb2srv_client_lookup_global(struct smbXsrv_client *client, > struct smbXsrv_client_table *table = client->table; > struct smbXsrv_client_global0 *global = NULL; > bool is_free = false; >- uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > struct db_record *db_rec; > >- key = smbXsrv_client_global_id_to_key(&client_guid, key_buf); >- >- db_rec = dbwrap_fetch_locked(table->global.db_ctx, >- talloc_tos(), key); >+ db_rec = smbXsrv_client_global_fetch_locked(table->global.db_ctx, >+ &client_guid, >+ talloc_tos()); > if (db_rec == NULL) { >- DBG_ERR("guid [%s]: Failed to lock key '%s'\n", >- GUID_string(talloc_tos(), &client_guid), >- hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); > return NT_STATUS_INTERNAL_DB_ERROR; > } > >@@ -681,8 +697,6 @@ NTSTATUS smbXsrv_client_update(struct smbXsrv_client *client) > { > struct smbXsrv_client_table *table = client->table; > NTSTATUS status; >- uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (client->global->db_rec != NULL) { > DBG_ERR("guid [%s]: Called with db_rec != NULL'\n", >@@ -691,15 +705,11 @@ NTSTATUS smbXsrv_client_update(struct smbXsrv_client *client) > return NT_STATUS_INTERNAL_ERROR; > } > >- key = smbXsrv_client_global_id_to_key(&client->global->client_guid, >- key_buf); >- >- client->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx, >- client->global, key); >+ client->global->db_rec = smbXsrv_client_global_fetch_locked( >+ table->global.db_ctx, >+ &client->global->client_guid, >+ client->global /* TALLOC_CTX */); > if (client->global->db_rec == NULL) { >- DBG_ERR("guid [%s]: Failed to lock key '%s'\n", >- GUID_string(talloc_tos(), &client->global->client_guid), >- hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); > return NT_STATUS_INTERNAL_DB_ERROR; > } > >@@ -730,8 +740,6 @@ NTSTATUS smbXsrv_client_remove(struct smbXsrv_client *client) > { > struct smbXsrv_client_table *table = client->table; > NTSTATUS status; >- uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE]; >- TDB_DATA key; > > if (client->global->db_rec != NULL) { > DBG_ERR("client_guid[%s]: Called with db_rec != NULL'\n", >@@ -743,15 +751,11 @@ NTSTATUS smbXsrv_client_remove(struct smbXsrv_client *client) > return NT_STATUS_OK; > } > >- key = smbXsrv_client_global_id_to_key(&client->global->client_guid, >- key_buf); >- >- client->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx, >- client->global, key); >+ client->global->db_rec = smbXsrv_client_global_fetch_locked( >+ table->global.db_ctx, >+ &client->global->client_guid, >+ client->global /* TALLOC_CTX */); > if (client->global->db_rec == NULL) { >- DBG_ERR("client_guid[%s]: Failed to lock key '%s'\n", >- GUID_string(talloc_tos(), &client->global->client_guid), >- hex_encode_talloc(talloc_tos(), key.dptr, key.dsize)); > return NT_STATUS_INTERNAL_DB_ERROR; > } > >-- >2.5.0 > > >From 7608685a6c8a2efa6757df0323ff95084daad68b Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sun, 28 Feb 2016 01:46:47 +0100 >Subject: [PATCH 15/40] smbd:smb2_creat: remove outdated TODO comments > >Leases have meanwhile been implemented and the >TODO has been taken care of. > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allson <jra@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Sun Feb 28 08:16:26 CET 2016 on sn-devel-144 >--- > source3/smbd/smb2_create.c | 8 -------- > 1 file changed, 8 deletions(-) > >diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c >index 62948a0..7917d42 100644 >--- a/source3/smbd/smb2_create.c >+++ b/source3/smbd/smb2_create.c >@@ -555,10 +555,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, > * (Note that the cases of an additional dh2q or dh2c blob > * which require a different error code, have been treated > * above.) >- * >- * TODO: >- * This is only true for the oplock case: >- * For leases, lease request is required additionally. > */ > > if (dhnq) { >@@ -595,10 +591,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, > * (Note that the cases of an additional dhnq, dhnc or dh2q > * blob which require a different error code, have been > * treated above.) >- * >- * TODO: >- * This is only true for the oplock case: >- * For leases, lease request is required additionally! > */ > > num_blobs_allowed = 1; >-- >2.5.0 > > >From a8e27384697aaf0ecd6620424298dcaee38f7cf9 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 29 Feb 2016 01:51:23 +0100 >Subject: [PATCH 16/40] torture:smb2: skip replay3 if server does not support > Multi-Channel > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/replay.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 4b3f569..71062c0 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -487,12 +487,20 @@ static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) > struct smb2_session *session1_2 = NULL; > uint32_t share_capabilities; > bool share_is_so; >+ uint32_t server_capabilities; > > if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) { > torture_skip(tctx, "SMB 3.X Dialect family required for " > "Replay tests\n"); > } > >+ server_capabilities = smb2cli_conn_server_capabilities( >+ tree1->session->transport->conn); >+ if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) { >+ torture_skip(tctx, >+ "Server does not support multi-channel."); >+ } >+ > share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli); > share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; > >-- >2.5.0 > > >From 7d8eb63dba8895bf3568cc5d1b76f13c5f345ef3 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 29 Feb 2016 01:52:07 +0100 >Subject: [PATCH 17/40] torture:smb2: skip replay5 test if server does not > support persistent handles > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/replay.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 71062c0..2b60cbf 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -877,6 +877,7 @@ static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree) > uint32_t share_capabilities; > bool share_is_ca; > bool share_is_so; >+ uint32_t server_capabilities; > const char *fname = BASEDIR "\\replay5.dat"; > struct smb2_transport *transport = tree->session->transport; > struct smbcli_options options = tree->session->transport->options; >@@ -888,6 +889,13 @@ static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree) > "Replay tests\n"); > } > >+ server_capabilities = smb2cli_conn_server_capabilities( >+ tree->session->transport->conn); >+ if (!(server_capabilities & SMB2_CAP_PERSISTENT_HANDLES)) { >+ torture_skip(tctx, >+ "Server does not support persistent handles."); >+ } >+ > share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); > > share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY; >-- >2.5.0 > > >From 18f61d0487f44225db6fc05bd0be5c7bc02653d6 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 29 Feb 2016 01:52:42 +0100 >Subject: [PATCH 18/40] torture:smb2: fix skip message if share is not CA > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/replay.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 2b60cbf..26c32d1 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -900,7 +900,7 @@ static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree) > > share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY; > if (!share_is_ca) { >- torture_skip(tctx, "Persistent File Handles not supported"); >+ torture_skip(tctx, "Share is not continuously available."); > } > > share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >-- >2.5.0 > > >From bb53badd19ba48358a0543b0b9c23d16fe04c503 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Thu, 25 Feb 2016 16:02:36 +0100 >Subject: [PATCH 19/40] dbwrap_util: improve a debug message in > dbwrap_delete_action() > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >--- > lib/dbwrap/dbwrap_util.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/lib/dbwrap/dbwrap_util.c b/lib/dbwrap/dbwrap_util.c >index 901ef56..5118fb7 100644 >--- a/lib/dbwrap/dbwrap_util.c >+++ b/lib/dbwrap/dbwrap_util.c >@@ -412,7 +412,8 @@ static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data) > > status = dbwrap_record_delete(rec); > if (!NT_STATUS_IS_OK(status)) { >- DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status))); >+ DBG_INFO("dbwrap_record_delete returned %s\n", >+ nt_errstr(status)); > } > > talloc_free(rec); >-- >2.5.0 > > >From d7e8b17debfa123b1a411c107b8e9dc87fc2f770 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Thu, 25 Feb 2016 00:56:14 +0100 >Subject: [PATCH 20/40] dbwrap: add dbwrap_purge[_bystring] > >Variants of dbrwap_delete[_bysrting] that treats NOT FOUND >as success. > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >--- > lib/dbwrap/dbwrap.h | 2 ++ > lib/dbwrap/dbwrap_util.c | 17 +++++++++++++++++ > 2 files changed, 19 insertions(+) > >diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h >index 5e13a59..2eded04 100644 >--- a/lib/dbwrap/dbwrap.h >+++ b/lib/dbwrap/dbwrap.h >@@ -94,6 +94,8 @@ const char *dbwrap_name(struct db_context *db); > > /* The following definitions come from lib/dbwrap_util.c */ > >+NTSTATUS dbwrap_purge(struct db_context *db, TDB_DATA key); >+NTSTATUS dbwrap_purge_bystring(struct db_context *db, const char *key); > NTSTATUS dbwrap_delete_bystring(struct db_context *db, const char *key); > NTSTATUS dbwrap_store_bystring(struct db_context *db, const char *key, > TDB_DATA data, int flags); >diff --git a/lib/dbwrap/dbwrap_util.c b/lib/dbwrap/dbwrap_util.c >index 5118fb7..22f910d 100644 >--- a/lib/dbwrap/dbwrap_util.c >+++ b/lib/dbwrap/dbwrap_util.c >@@ -528,6 +528,23 @@ NTSTATUS dbwrap_trans_traverse(struct db_context *db, > return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx); > } > >+NTSTATUS dbwrap_purge(struct db_context *db, TDB_DATA key) >+{ >+ NTSTATUS status; >+ >+ status = dbwrap_delete(db, key); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { >+ status = NT_STATUS_OK; >+ } >+ >+ return status; >+} >+ >+NTSTATUS dbwrap_purge_bystring(struct db_context *db, const char *key) >+{ >+ return dbwrap_purge(db, string_term_tdb_data(key)); >+} >+ > NTSTATUS dbwrap_delete_bystring(struct db_context *db, const char *key) > { > return dbwrap_delete(db, string_term_tdb_data(key)); >-- >2.5.0 > > >From ce5c0e3518d03e1f42d9d988fd70166b37b80ec9 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Thu, 25 Feb 2016 00:58:50 +0100 >Subject: [PATCH 21/40] s3:registry: use dbwrap_purge_bystring instead of > dbwrap_delete_bystring > >where appropriate > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >--- > source3/registry/reg_backend_db.c | 7 +------ > 1 file changed, 1 insertion(+), 6 deletions(-) > >diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c >index 7b3391d..bdfe7d2 100644 >--- a/source3/registry/reg_backend_db.c >+++ b/source3/registry/reg_backend_db.c >@@ -966,12 +966,7 @@ static WERROR regdb_delete_key_with_prefix(struct db_context *db, > goto done; > } > >- werr = ntstatus_to_werror(dbwrap_delete_bystring(db, path)); >- >- /* treat "not found" as ok */ >- if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) { >- werr = WERR_OK; >- } >+ werr = ntstatus_to_werror(dbwrap_purge_bystring(db, path)); > > done: > talloc_free(mem_ctx); >-- >2.5.0 > > >From 5716c46a677f37b7eb863bc40d901db5acce03b6 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Thu, 25 Feb 2016 16:15:04 +0100 >Subject: [PATCH 22/40] netlogon_creds_cli: use dbwrap_purge instead of > dbwrap_delete where appropriate > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >--- > libcli/auth/netlogon_creds_cli.c | 14 ++++---------- > 1 file changed, 4 insertions(+), 10 deletions(-) > >diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c >index 7c867cf..38b1351 100644 >--- a/libcli/auth/netlogon_creds_cli.c >+++ b/libcli/auth/netlogon_creds_cli.c >@@ -1031,11 +1031,8 @@ struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, > return req; > } > >- status = dbwrap_delete(state->context->db.ctx, >- state->context->db.key_data); >- if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { >- status = NT_STATUS_OK; >- } >+ status = dbwrap_purge(state->context->db.ctx, >+ state->context->db.key_data); > if (tevent_req_nterror(req, status)) { > return tevent_req_post(req, ev); > } >@@ -1065,11 +1062,8 @@ static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq) > } > state->locked_state->is_glocked = true; > >- status = dbwrap_delete(state->context->db.ctx, >- state->context->db.key_data); >- if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { >- status = NT_STATUS_OK; >- } >+ status = dbwrap_purge(state->context->db.ctx, >+ state->context->db.key_data); > if (tevent_req_nterror(req, status)) { > return; > } >-- >2.5.0 > > >From fbf50a003467594c005ea82f0045efef74af9725 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 1 Mar 2016 20:40:47 +0100 >Subject: [PATCH 23/40] smbd: fix crash in smbXsrv_client_global_remove() > >Probably copy-n-paste error. >Uncovered by the multi-channel-related tests we're >currently writing to exercise this code more. > >Pair-Programmed-With: Guenther Deschner <gd@samba.org> > >Signed-off-by: Michael Adam <obnox@samba.org> >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >--- > source3/smbd/smbXsrv_client.c | 8 ++------ > 1 file changed, 2 insertions(+), 6 deletions(-) > >diff --git a/source3/smbd/smbXsrv_client.c b/source3/smbd/smbXsrv_client.c >index 2dd4cad..d8ba2f7 100644 >--- a/source3/smbd/smbXsrv_client.c >+++ b/source3/smbd/smbXsrv_client.c >@@ -428,7 +428,6 @@ static NTSTATUS smbXsrv_client_global_store(struct smbXsrv_client_global0 *globa > > static NTSTATUS smbXsrv_client_global_remove(struct smbXsrv_client_global0 *global) > { >- struct smbXsrv_client_globalB global_blob; > TDB_DATA key; > NTSTATUS status; > >@@ -453,11 +452,8 @@ static NTSTATUS smbXsrv_client_global_remove(struct smbXsrv_client_global0 *glob > return status; > } > global->stored = false; >- if (DEBUGLVL(DBGLVL_DEBUG)) { >- DBG_DEBUG("key '%s' delete\n", >- hex_encode_talloc(global->db_rec, key.dptr, key.dsize)); >- NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob); >- } >+ DBG_DEBUG("key '%s' delete\n", >+ hex_encode_talloc(global->db_rec, key.dptr, key.dsize)); > > TALLOC_FREE(global->db_rec); > >-- >2.5.0 > > >From 64e731a11d22965d5de52275260a208bf30a9a88 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 1 Mar 2016 23:07:06 +0100 >Subject: [PATCH 24/40] torture:smb2: skip replay4 if server does not support > multi-channel > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> > >Autobuild-User(master): Michael Adam <obnox@samba.org> >Autobuild-Date(master): Wed Mar 2 20:38:49 CET 2016 on sn-devel-144 >--- > source4/torture/smb2/replay.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 26c32d1..21f6f80 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -650,12 +650,20 @@ static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1) > uint16_t curr_cs; > uint32_t share_capabilities; > bool share_is_so; >+ uint32_t server_capabilities; > > if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) { > torture_skip(tctx, "SMB 3.X Dialect family required for " > "Replay tests\n"); > } > >+ server_capabilities = smb2cli_conn_server_capabilities( >+ tree1->session->transport->conn); >+ if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) { >+ torture_skip(tctx, >+ "Server does not support multi-channel."); >+ } >+ > share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli); > share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; > >-- >2.5.0 > > >From 26be9597d7b74a1e8877ff32cde40b246c66fdc5 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 1 Mar 2016 01:14:48 +0100 >Subject: [PATCH 25/40] torture:smb2: rename replay1 -> replay-commands > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 2 +- > source4/torture/smb2/replay.c | 6 +++--- > 2 files changed, 4 insertions(+), 4 deletions(-) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 04a0621..b1222f0 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -202,7 +202,7 @@ > ^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.replay-commands > ^samba3.smb2.replay.replay2 > ^samba3.smb2.replay.replay3 > ^samba3.smb2.replay.replay4 >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 21f6f80..cef682a 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -161,7 +161,7 @@ static bool torture_oplock_ack_handler(struct smb2_transport *transport, > * Test what happens when SMB2_FLAGS_REPLAY_OPERATION is enabled for various > * commands. We want to verify if the server returns an error code or not. > */ >-static bool test_replay1(struct torture_context *tctx, struct smb2_tree *tree) >+static bool test_replay_commands(struct torture_context *tctx, struct smb2_tree *tree) > { > bool ret = true; > NTSTATUS status; >@@ -175,7 +175,7 @@ static bool test_replay1(struct torture_context *tctx, struct smb2_tree *tree) > struct smb2_lock_element el[2]; > struct smb2_flush f; > TALLOC_CTX *tmp_ctx = talloc_new(tree); >- const char *fname = BASEDIR "\\replay1.dat"; >+ const char *fname = BASEDIR "\\replay_commands.dat"; > struct smb2_transport *transport = tree->session->transport; > > if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >@@ -997,7 +997,7 @@ struct torture_suite *torture_smb2_replay_init(void) > struct torture_suite *suite = > torture_suite_create(talloc_autofree_context(), "replay"); > >- torture_suite_add_1smb2_test(suite, "replay1", test_replay1); >+ torture_suite_add_1smb2_test(suite, "replay-commands", test_replay_commands); > torture_suite_add_1smb2_test(suite, "replay2", test_replay2); > torture_suite_add_1smb2_test(suite, "replay3", test_replay3); > torture_suite_add_1smb2_test(suite, "replay4", test_replay4); >-- >2.5.0 > > >From 822540987c802d7ad8a2b8c8725188d8a8b23b7c Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 1 Mar 2016 01:18:03 +0100 >Subject: [PATCH 26/40] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 5 +- > source4/torture/smb2/replay.c | 384 +++++++++++++++++++++++++++++++++++++----- > 2 files changed, 342 insertions(+), 47 deletions(-) > >diff --git a/selftest/knownfail b/selftest/knownfail >index b1222f0..847415e 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -203,7 +203,10 @@ > ^samba3.smb2.session.*reauth5 # some special anonymous checks? > ^samba3.smb2.compound.interim2 # wrong return code (STATUS_CANCELLED) > ^samba3.smb2.replay.replay-commands >-^samba3.smb2.replay.replay2 >+^samba3.smb2.replay.replay-regular >+^samba3.smb2.replay.replay-dhv2-oplock1 >+^samba3.smb2.replay.replay-dhv2-oplock2 >+^samba3.smb2.replay.replay-dhv2-oplock3 > ^samba3.smb2.replay.replay3 > ^samba3.smb2.replay.replay4 > ^samba3.smb2.lock.*replay >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index cef682a..561963a 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -287,20 +287,136 @@ done: > } > > /** >- * Test Durablity V2 Create Replay Detection on Single Channel. Also verify that >- * regular creates can not be replayed. >+ * Test replay detection without create GUID on single channel. >+ * Regular creates can not be replayed. >+ * The return code is unaffected of the REPLAY_OPERATION flag. > */ >-static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) >+static bool test_replay_regular(struct torture_context *tctx, >+ struct smb2_tree *tree) > { > NTSTATUS status; > TALLOC_CTX *mem_ctx = talloc_new(tctx); > struct smb2_handle _h; > struct smb2_handle *h = NULL; >- struct smb2_create io, ref1, ref2; >- struct GUID create_guid = GUID_random(); >+ struct smb2_create io; > uint32_t perms = 0; > bool ret = true; >- const char *fname = BASEDIR "\\replay2.dat"; >+ const char *fname = BASEDIR "\\replay_regular.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h); >+ CHECK_VAL(break_info.count, 0); >+ >+ torture_comment(tctx, "No replay detection for regular create\n"); >+ >+ perms = SEC_STD_SYNCHRONIZE | SEC_STD_READ_CONTROL | SEC_STD_DELETE | >+ SEC_DIR_WRITE_ATTRIBUTE | SEC_DIR_READ_ATTRIBUTE | >+ SEC_DIR_WRITE_EA | SEC_FILE_APPEND_DATA | >+ SEC_FILE_WRITE_DATA; >+ >+ io = (struct smb2_create) { >+ .in.desired_access = perms, >+ .in.file_attributes = 0, >+ .in.create_disposition = NTCREATEX_DISP_CREATE, >+ .in.share_access = NTCREATEX_SHARE_ACCESS_DELETE, >+ .in.create_options = 0x0, >+ .in.fname = fname >+ }; >+ >+ status = smb2_create(tree, tctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VAL(break_info.count, 0); >+ _h = io.out.file.handle; >+ h = &_h; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, tctx, &io); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); >+ CHECK_VAL(break_info.count, 0); >+ >+ smb2_util_close(tree, *h); >+ h = NULL; >+ smb2_util_unlink(tree, fname); >+ >+ /* >+ * Same experiment with different create disposition. >+ */ >+ io.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ status = smb2_create(tree, tctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VAL(break_info.count, 0); >+ _h = io.out.file.handle; >+ h = &_h; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, tctx, &io); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); >+ CHECK_VAL(break_info.count, 0); >+ >+ smb2_util_close(tree, *h); >+ h = NULL; >+ smb2_util_unlink(tree, fname); >+ >+ /* >+ * Now with more generous share mode. >+ */ >+ io.in.share_access = smb2_util_share_access("RWD"); >+ status = smb2_create(tree, tctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VAL(break_info.count, 0); >+ _h = io.out.file.handle; >+ h = &_h; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, tctx, &io); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VAL(break_info.count, 0); >+ >+done: >+ if (h != NULL) { >+ smb2_util_close(tree, *h); >+ } >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+/** >+ * Test Durablity V2 Create Replay Detection on Single Channel. >+ */ >+static bool test_replay_dhv2_oplock1(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h; >+ struct smb2_handle *h = NULL; >+ struct smb2_create io, ref1; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat"; > struct smb2_transport *transport = tree->session->transport; > uint32_t share_capabilities; > bool share_is_so; >@@ -362,14 +478,98 @@ static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) > CHECK_CREATE_OUT(&io, &ref1); > CHECK_VAL(break_info.count, 0); > >+done: >+ if (h != NULL) { >+ smb2_util_close(tree, *h); >+ } >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+/** >+ * Test Durablity V2 Create Replay Detection on Single Channel. >+ * Hand in a different oplock level in the replay. >+ * Server responds with the handed in oplock level and >+ * corresponding durable status, but does not change the >+ * oplock level or durable status of the opened file. >+ */ >+static bool test_replay_dhv2_oplock2(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h; >+ struct smb2_handle *h = NULL; >+ struct smb2_create io, ref1, ref2; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay_dhv2_oplock2.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Replay of DurableHandleReqV2 on Single " >+ "Channel\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h); >+ CHECK_VAL(break_info.count, 0); >+ >+ smb2_oplock_create_share(&io, fname, >+ smb2_util_share_access(""), >+ smb2_util_oplock_level("b")); >+ io.in.durable_open = false; >+ io.in.durable_open_v2 = true; >+ io.in.persistent_open = false; >+ io.in.create_guid = create_guid; >+ io.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ ref1 = io; >+ _h = io.out.file.handle; >+ h = &_h; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io.out.durable_open, false); >+ if (share_is_so) { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s")); >+ CHECK_VAL(io.out.durable_open_v2, false); >+ CHECK_VAL(io.out.timeout, 0); >+ } else { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ CHECK_VAL(io.out.timeout, io.in.timeout); >+ } >+ > /* >- * See how server behaves if we change some of the Create params while >- * Replaying. Change Share Access and Oplock Level. It seems the server >- * does not care for change in these parameters. The server seems to >- * only care for the File Name and GUID >+ * Replay durable v2 create on single channel: >+ * >+ * Replay the create with a different oplock (none). >+ * The server replies with the requested oplock level >+ * and also only replies with durable handle based >+ * on whether it could have been granted based on >+ * the requested oplock type. > */ > smb2_oplock_create_share(&io, fname, >- smb2_util_share_access("RWD"), >+ smb2_util_share_access(""), > smb2_util_oplock_level("")); > io.in.durable_open = false; > io.in.durable_open_v2 = true; >@@ -378,9 +578,7 @@ static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) > io.in.timeout = UINT32_MAX; > > /* >- * The output will just react on the >- * input, but it doesn't change the oplock >- * or share access values on the existing open >+ * Adapt the response to the exepected values > */ > ref2 = ref1; > ref2.out.oplock_level = smb2_util_oplock_level(""); >@@ -396,11 +594,17 @@ static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) > CHECK_VAL(break_info.count, 0); > > /* >- * This is a normal open, which triggers an oplock >- * break and still gets NT_STATUS_SHARING_VIOLATION >+ * Prove that the open file still has a batch oplock >+ * by breaking it with another open. > */ >- io = ref1; >- io.in.durable_open_v2 = false; >+ smb2_oplock_create_share(&io, fname, >+ smb2_util_share_access(""), >+ smb2_util_oplock_level("b")); >+ io.in.durable_open = false; >+ io.in.durable_open_v2 = true; >+ io.in.persistent_open = false; >+ io.in.create_guid = GUID_random(); >+ io.in.timeout = UINT32_MAX; > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); > >@@ -411,48 +615,133 @@ static bool test_replay2(struct torture_context *tctx, struct smb2_tree *tree) > ZERO_STRUCT(break_info); > } > >- smb2_util_close(tree, *h); >- h = NULL; >- status = smb2_util_unlink(tree, fname); >- CHECK_STATUS(status, NT_STATUS_OK); >- CHECK_VAL(break_info.count, 0); >+done: >+ if (h != NULL) { >+ smb2_util_close(tree, *h); >+ } >+ smb2_deltree(tree, BASEDIR); > >- /* >- * No Replay detection for regular Creates >- */ >- perms = SEC_STD_SYNCHRONIZE | SEC_STD_READ_CONTROL | SEC_STD_DELETE | >- SEC_DIR_WRITE_ATTRIBUTE | SEC_DIR_READ_ATTRIBUTE | >- SEC_DIR_WRITE_EA | SEC_FILE_APPEND_DATA | >- SEC_FILE_WRITE_DATA; >+ talloc_free(tree); >+ talloc_free(mem_ctx); > >- io = (struct smb2_create) { >- .in.desired_access = perms, >- .in.file_attributes = 0, >- .in.create_disposition = NTCREATEX_DISP_CREATE, >- .in.share_access = NTCREATEX_SHARE_ACCESS_DELETE, >- .in.create_options = 0x0, >- .in.fname = fname >- }; >+ return ret; >+} > >- status = smb2_create(tree, tctx, &io); >+/** >+ * Test Durablity V2 Create Replay Detection on Single Channel. >+ * Replay with a different share mode. The share mode of >+ * the opened file is not changed by this. >+ */ >+static bool test_replay_dhv2_oplock3(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h; >+ struct smb2_handle *h = NULL; >+ struct smb2_create io, ref1; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay_dhv2_oplock3.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Replay of DurableHandleReqV2 on Single " >+ "Channel\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h); > CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h); > CHECK_VAL(break_info.count, 0); >+ >+ smb2_oplock_create_share(&io, fname, >+ smb2_util_share_access(""), >+ smb2_util_oplock_level("b")); >+ io.in.durable_open = false; >+ io.in.durable_open_v2 = true; >+ io.in.persistent_open = false; >+ io.in.create_guid = create_guid; >+ io.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ ref1 = io; > _h = io.out.file.handle; > h = &_h; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io.out.durable_open, false); >+ if (share_is_so) { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s")); >+ CHECK_VAL(io.out.durable_open_v2, false); >+ CHECK_VAL(io.out.timeout, 0); >+ } else { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ CHECK_VAL(io.out.timeout, io.in.timeout); >+ } > >- torture_comment(tctx, "No Replay Detection for regular Create\n"); > /* >- * Now replay the same create >+ * Replay durable v2 create on single channel: >+ * >+ * Replay the create with a different share mode. >+ * The server replies with the requested share >+ * mode instead of that which is associated to >+ * the handle. > */ >+ smb2_oplock_create_share(&io, fname, >+ smb2_util_share_access("RWD"), >+ smb2_util_oplock_level("b")); >+ io.in.durable_open = false; >+ io.in.durable_open_v2 = true; >+ io.in.persistent_open = false; >+ io.in.create_guid = create_guid; >+ io.in.timeout = UINT32_MAX; >+ > smb2cli_session_start_replay(tree->session->smbXcli); >- status = smb2_create(tree, tctx, &io); >- CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); >+ status = smb2_create(tree, mem_ctx, &io); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATE_OUT(&io, &ref1); > CHECK_VAL(break_info.count, 0); > >-done: >- smb2cli_session_stop_replay(tree->session->smbXcli); >+ /* >+ * In order to prove that the different share mode in the >+ * replayed create had no effect on the open file handle, >+ * show that a new create yields NT_STATUS_SHARING_VIOLATION. >+ */ >+ smb2_oplock_create_share(&io, fname, >+ smb2_util_share_access(""), >+ smb2_util_oplock_level("b")); >+ io.in.durable_open = false; >+ io.in.durable_open_v2 = true; >+ io.in.persistent_open = false; >+ io.in.create_guid = GUID_random(); >+ io.in.timeout = UINT32_MAX; >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); > >+ if (!share_is_so) { >+ CHECK_VAL(break_info.count, 1); >+ CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle); >+ CHECK_VAL(break_info.level, smb2_util_oplock_level("s")); >+ ZERO_STRUCT(break_info); >+ } >+ >+done: > if (h != NULL) { > smb2_util_close(tree, *h); > } >@@ -998,7 +1287,10 @@ struct torture_suite *torture_smb2_replay_init(void) > torture_suite_create(talloc_autofree_context(), "replay"); > > torture_suite_add_1smb2_test(suite, "replay-commands", test_replay_commands); >- torture_suite_add_1smb2_test(suite, "replay2", test_replay2); >+ torture_suite_add_1smb2_test(suite, "replay-regular", test_replay_regular); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3); > torture_suite_add_1smb2_test(suite, "replay3", test_replay3); > torture_suite_add_1smb2_test(suite, "replay4", test_replay4); > torture_suite_add_1smb2_test(suite, "replay5", test_replay5); >-- >2.5.0 > > >From e570d4e830f67eb1665f473d87ccc9f846427dba Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 29 Feb 2016 19:00:42 +0100 >Subject: [PATCH 27/40] torture:smb2:replay: extend CHECK_CREATE_OUT() to know > leases > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source4/torture/smb2/replay.c | 5 +++++ > 1 file changed, 5 insertions(+) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 561963a..741fa4e 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -85,6 +85,11 @@ > __IO_OUT_VAL(__io1, __io2, persistent_open); \ > __IO_OUT_VAL(__io1, __io2, timeout); \ > __IO_OUT_VAL(__io1, __io2, blobs.num_blobs); \ >+ if ((__io1)->out.oplock_level == SMB2_OPLOCK_LEVEL_LEASE) { \ >+ __IO_OUT_VAL(__io1, __io2, lease_response.lease_state);\ >+ __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[0]);\ >+ __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[1]);\ >+ } \ > } while(0) > > #define BASEDIR "replaytestdir" >-- >2.5.0 > > >From 6dbed40f161539b8ef4a16271b4ec4507210d1a9 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 29 Feb 2016 18:23:04 +0100 >Subject: [PATCH 28/40] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 1 + > source4/torture/smb2/replay.c | 139 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 140 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 847415e..3a61c1d 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -207,6 +207,7 @@ > ^samba3.smb2.replay.replay-dhv2-oplock1 > ^samba3.smb2.replay.replay-dhv2-oplock2 > ^samba3.smb2.replay.replay-dhv2-oplock3 >+^samba3.smb2.replay.replay-dhv2-lease1 > ^samba3.smb2.replay.replay3 > ^samba3.smb2.replay.replay4 > ^samba3.smb2.lock.*replay >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 741fa4e..050398e 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -759,6 +759,144 @@ done: > } > > /** >+ * Test durablity v2 create replay detection on single channel. >+ * Variant with leases instead of oplocks: >+ * - open a file with a rh lease >+ * - upgrade to a rwh lease with a second create >+ * - replay the first create. >+ * ==> it gets back the upgraded lease level >+ */ >+static bool test_replay_dhv2_lease1(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h1; >+ struct smb2_handle *h1 = NULL; >+ struct smb2_handle _h2; >+ struct smb2_handle *h2 = NULL; >+ struct smb2_create io1, io2, ref1; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay2_lease1.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; >+ uint32_t server_capabilities; >+ struct smb2_lease ls1, ls2; >+ uint64_t lease_key; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ server_capabilities = smb2cli_conn_server_capabilities(transport->conn); >+ if (!(server_capabilities & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease " >+ "on Single Channel\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h1); >+ CHECK_VAL(break_info.count, 0); >+ >+ lease_key = random(); >+ >+ smb2_lease_create(&io1, &ls1, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RH")); >+ io1.in.durable_open = false; >+ io1.in.durable_open_v2 = true; >+ io1.in.persistent_open = false; >+ io1.in.create_guid = create_guid; >+ io1.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ ref1 = io1; >+ _h1 = io1.out.file.handle; >+ h1 = &_h1; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io1.out.durable_open, false); >+ CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key); >+ if (share_is_so) { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("R")); >+ CHECK_VAL(io1.out.durable_open_v2, false); >+ CHECK_VAL(io1.out.timeout, 0); >+ } else { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("RH")); >+ CHECK_VAL(io1.out.durable_open_v2, true); >+ CHECK_VAL(io1.out.timeout, io1.in.timeout); >+ } >+ >+ /* >+ * Upgrade the lease to RWH >+ */ >+ smb2_lease_create(&io2, &ls2, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RHW")); >+ io2.in.durable_open = false; >+ io2.in.durable_open_v2 = true; >+ io2.in.persistent_open = false; >+ io2.in.create_guid = GUID_random(); /* new guid... */ >+ io2.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ _h2 = io2.out.file.handle; >+ h2 = &_h2; >+ >+ /* >+ * Replay Durable V2 Create on single channel. >+ * We get the io from open #1 but with the >+ * upgraded lease. >+ */ >+ >+ /* adapt expected lease in response */ >+ if (!share_is_so) { >+ ref1.out.lease_response.lease_state = >+ smb2_util_lease_state("RHW"); >+ } >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, mem_ctx, &io1); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATE_OUT(&io1, &ref1); >+ CHECK_VAL(break_info.count, 0); >+ >+done: >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ >+ if (h1 != NULL) { >+ smb2_util_close(tree, *h1); >+ } >+ if (h2 != NULL) { >+ smb2_util_close(tree, *h2); >+ } >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+/** > * Test Durablity V2 Create Replay Detection on Multi Channel > */ > static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) >@@ -1296,6 +1434,7 @@ struct torture_suite *torture_smb2_replay_init(void) > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1); > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2); > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1); > torture_suite_add_1smb2_test(suite, "replay3", test_replay3); > torture_suite_add_1smb2_test(suite, "replay4", test_replay4); > torture_suite_add_1smb2_test(suite, "replay5", test_replay5); >-- >2.5.0 > > >From 0d632bbefe081a9a020d0d9951a5a261caac6f3f Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 29 Feb 2016 19:04:32 +0100 >Subject: [PATCH 29/40] torture:smb2: add smb2.replay.replay-dhv2-lease2 > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 1 + > source4/torture/smb2/replay.c | 152 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 153 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 3a61c1d..abca6a9 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -208,6 +208,7 @@ > ^samba3.smb2.replay.replay-dhv2-oplock2 > ^samba3.smb2.replay.replay-dhv2-oplock3 > ^samba3.smb2.replay.replay-dhv2-lease1 >+^samba3.smb2.replay.replay-dhv2-lease2 > ^samba3.smb2.replay.replay3 > ^samba3.smb2.replay.replay4 > ^samba3.smb2.lock.*replay >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 050398e..600a8a6 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -897,6 +897,157 @@ done: > } > > /** >+ * Test durablity v2 create replay detection on single channel. >+ * Variant with leases instead of oplocks, where the >+ * replay does not specify the original lease level but >+ * just a "R" lease. This still gives the upgraded lease >+ * level in the reply. >+ * - open a file with a rh lease >+ * - upgrade to a rwh lease with a second create >+ * - replay the first create. >+ * ==> it gets back the upgraded lease level >+ */ >+static bool test_replay_dhv2_lease2(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h1; >+ struct smb2_handle *h1 = NULL; >+ struct smb2_handle _h2; >+ struct smb2_handle *h2 = NULL; >+ struct smb2_create io1, io2, ref1; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay2_lease2.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; >+ uint32_t server_capabilities; >+ struct smb2_lease ls1, ls2; >+ uint64_t lease_key; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ server_capabilities = smb2cli_conn_server_capabilities(transport->conn); >+ if (!(server_capabilities & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease " >+ "on Single Channel\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h1); >+ CHECK_VAL(break_info.count, 0); >+ >+ lease_key = random(); >+ >+ smb2_lease_create(&io1, &ls1, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RH")); >+ io1.in.durable_open = false; >+ io1.in.durable_open_v2 = true; >+ io1.in.persistent_open = false; >+ io1.in.create_guid = create_guid; >+ io1.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io1.out.durable_open, false); >+ CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key); >+ if (share_is_so) { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("R")); >+ CHECK_VAL(io1.out.durable_open_v2, false); >+ CHECK_VAL(io1.out.timeout, 0); >+ } else { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("RH")); >+ CHECK_VAL(io1.out.durable_open_v2, true); >+ CHECK_VAL(io1.out.timeout, io1.in.timeout); >+ } >+ ref1 = io1; >+ _h1 = io1.out.file.handle; >+ h1 = &_h1; >+ >+ /* >+ * Upgrade the lease to RWH >+ */ >+ smb2_lease_create(&io2, &ls2, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RHW")); >+ io2.in.durable_open = false; >+ io2.in.durable_open_v2 = true; >+ io2.in.persistent_open = false; >+ io2.in.create_guid = GUID_random(); /* new guid... */ >+ io2.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ _h2 = io2.out.file.handle; >+ h2 = &_h2; >+ >+ /* >+ * Replay Durable V2 Create on single channel. >+ * Changing the requested lease level to "R" >+ * does not change the response: >+ * We get the reply from open #1 but with the >+ * upgraded lease. >+ */ >+ >+ /* adapt the expected response */ >+ if (!share_is_so) { >+ ref1.out.lease_response.lease_state = >+ smb2_util_lease_state("RHW"); >+ } >+ >+ smb2_lease_create(&io1, &ls1, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("R")); >+ io1.in.durable_open = false; >+ io1.in.durable_open_v2 = true; >+ io1.in.persistent_open = false; >+ io1.in.create_guid = create_guid; >+ io1.in.timeout = UINT32_MAX; >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, mem_ctx, &io1); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATE_OUT(&io1, &ref1); >+ CHECK_VAL(break_info.count, 0); >+ >+done: >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ >+ if (h1 != NULL) { >+ smb2_util_close(tree, *h1); >+ } >+ if (h2 != NULL) { >+ smb2_util_close(tree, *h2); >+ } >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+/** > * Test Durablity V2 Create Replay Detection on Multi Channel > */ > static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) >@@ -1435,6 +1586,7 @@ struct torture_suite *torture_smb2_replay_init(void) > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2); > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2", test_replay_dhv2_lease2); > torture_suite_add_1smb2_test(suite, "replay3", test_replay3); > torture_suite_add_1smb2_test(suite, "replay4", test_replay4); > torture_suite_add_1smb2_test(suite, "replay5", test_replay5); >-- >2.5.0 > > >From 440e8b97ce2f666bfdcb19b9d258884e10ffee28 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 1 Mar 2016 23:03:50 +0100 >Subject: [PATCH 30/40] torture:smb2: add smb2.replay.replay-dhv2-lease-oplock > >Open with a lease and replay with an oplock. > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 1 + > source4/torture/smb2/replay.c | 145 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 146 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index abca6a9..dab4dbe 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -209,6 +209,7 @@ > ^samba3.smb2.replay.replay-dhv2-oplock3 > ^samba3.smb2.replay.replay-dhv2-lease1 > ^samba3.smb2.replay.replay-dhv2-lease2 >+^samba3.smb2.replay.replay-dhv2-lease-oplock > ^samba3.smb2.replay.replay3 > ^samba3.smb2.replay.replay4 > ^samba3.smb2.lock.*replay >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 600a8a6..16d97bc 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -1048,6 +1048,150 @@ done: > } > > /** >+ * Test durablity v2 create replay detection on single channel. >+ * Do the original create with a lease, and do the replay >+ * with an oplock. >+ */ >+static bool test_replay_dhv2_lease_oplock(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h1; >+ struct smb2_handle *h1 = NULL; >+ struct smb2_handle _h2; >+ struct smb2_handle *h2 = NULL; >+ struct smb2_create io1, io2, ref1; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay2_lease1.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; >+ uint32_t server_capabilities; >+ struct smb2_lease ls1, ls2; >+ uint64_t lease_key; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ server_capabilities = smb2cli_conn_server_capabilities(transport->conn); >+ if (!(server_capabilities & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease " >+ "on Single Channel\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h1); >+ CHECK_VAL(break_info.count, 0); >+ >+ lease_key = random(); >+ >+ smb2_lease_create(&io1, &ls1, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RH")); >+ io1.in.durable_open = false; >+ io1.in.durable_open_v2 = true; >+ io1.in.persistent_open = false; >+ io1.in.create_guid = create_guid; >+ io1.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ ref1 = io1; >+ _h1 = io1.out.file.handle; >+ h1 = &_h1; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io1.out.durable_open, false); >+ CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key); >+ if (share_is_so) { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("R")); >+ CHECK_VAL(io1.out.durable_open_v2, false); >+ CHECK_VAL(io1.out.timeout, 0); >+ } else { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("RH")); >+ CHECK_VAL(io1.out.durable_open_v2, true); >+ CHECK_VAL(io1.out.timeout, io1.in.timeout); >+ } >+ >+ /* >+ * Upgrade the lease to RWH >+ */ >+ smb2_lease_create(&io2, &ls2, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RHW")); >+ io2.in.durable_open = false; >+ io2.in.durable_open_v2 = true; >+ io2.in.persistent_open = false; >+ io2.in.create_guid = GUID_random(); /* new guid... */ >+ io2.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ _h2 = io2.out.file.handle; >+ h2 = &_h2; >+ >+ /* >+ * Replay Durable V2 Create on single channel. >+ * We get the io from open #1 but with the >+ * upgraded lease. >+ */ >+ >+ smb2_oplock_create_share(&io2, fname, >+ smb2_util_share_access(""), >+ smb2_util_oplock_level("b")); >+ io2.in.durable_open = false; >+ io2.in.durable_open_v2 = true; >+ io2.in.persistent_open = false; >+ io2.in.create_guid = create_guid; >+ io2.in.timeout = UINT32_MAX; >+ >+ /* adapt expected lease in response */ >+ if (!share_is_so) { >+ ref1.out.lease_response.lease_state = >+ smb2_util_lease_state("RHW"); >+ } >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, mem_ctx, &io1); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATE_OUT(&io1, &ref1); >+ CHECK_VAL(break_info.count, 0); >+ >+done: >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ >+ if (h1 != NULL) { >+ smb2_util_close(tree, *h1); >+ } >+ if (h2 != NULL) { >+ smb2_util_close(tree, *h2); >+ } >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+/** > * Test Durablity V2 Create Replay Detection on Multi Channel > */ > static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) >@@ -1587,6 +1731,7 @@ struct torture_suite *torture_smb2_replay_init(void) > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2", test_replay_dhv2_lease2); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock", test_replay_dhv2_lease_oplock); > torture_suite_add_1smb2_test(suite, "replay3", test_replay3); > torture_suite_add_1smb2_test(suite, "replay4", test_replay4); > torture_suite_add_1smb2_test(suite, "replay5", test_replay5); >-- >2.5.0 > > >From c3a35e584a22195af0cf0f58b89807e2833d9cc8 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Wed, 2 Mar 2016 01:38:24 +0100 >Subject: [PATCH 31/40] torture:smb2: add smb2.replay.replay-oplock-lease > >create with an oplock, and replay with a lease. > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 1 + > source4/torture/smb2/replay.c | 105 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 106 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index dab4dbe..3796ac4 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -207,6 +207,7 @@ > ^samba3.smb2.replay.replay-dhv2-oplock1 > ^samba3.smb2.replay.replay-dhv2-oplock2 > ^samba3.smb2.replay.replay-dhv2-oplock3 >+^samba3.smb2.replay.replay-dhv2-oplock-lease > ^samba3.smb2.replay.replay-dhv2-lease1 > ^samba3.smb2.replay.replay-dhv2-lease2 > ^samba3.smb2.replay.replay-dhv2-lease-oplock >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 16d97bc..d541f7a 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -759,6 +759,110 @@ done: > } > > /** >+ * Test Durablity V2 Create Replay Detection on Single Channel. >+ * Create with an oplock, and replay with a lease. >+ */ >+static bool test_replay_dhv2_oplock_lease(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h; >+ struct smb2_handle *h = NULL; >+ struct smb2_create io; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; >+ uint32_t server_capabilities; >+ struct smb2_lease ls; >+ uint64_t lease_key; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ server_capabilities = smb2cli_conn_server_capabilities(transport->conn); >+ if (!(server_capabilities & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Replay of DurableHandleReqV2 on Single " >+ "Channel\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h); >+ CHECK_VAL(break_info.count, 0); >+ >+ smb2_oplock_create_share(&io, fname, >+ smb2_util_share_access(""), >+ smb2_util_oplock_level("b")); >+ io.in.durable_open = false; >+ io.in.durable_open_v2 = true; >+ io.in.persistent_open = false; >+ io.in.create_guid = create_guid; >+ io.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ _h = io.out.file.handle; >+ h = &_h; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io.out.durable_open, false); >+ if (share_is_so) { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s")); >+ CHECK_VAL(io.out.durable_open_v2, false); >+ CHECK_VAL(io.out.timeout, 0); >+ } else { >+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ CHECK_VAL(io.out.timeout, io.in.timeout); >+ } >+ >+ /* >+ * Replay Durable V2 Create on single channel >+ * but replay it with a lease instead of an oplock. >+ */ >+ lease_key = random(); >+ smb2_lease_create(&io, &ls, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RH")); >+ io.in.durable_open = false; >+ io.in.durable_open_v2 = true; >+ io.in.persistent_open = false; >+ io.in.create_guid = create_guid; >+ io.in.timeout = UINT32_MAX; >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, mem_ctx, &io); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); >+ >+done: >+ if (h != NULL) { >+ smb2_util_close(tree, *h); >+ } >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+ >+/** > * Test durablity v2 create replay detection on single channel. > * Variant with leases instead of oplocks: > * - open a file with a rh lease >@@ -1729,6 +1833,7 @@ struct torture_suite *torture_smb2_replay_init(void) > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1); > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2); > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2", test_replay_dhv2_lease2); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock", test_replay_dhv2_lease_oplock); >-- >2.5.0 > > >From 2fec45db158a8e2bd1795f4a519afcc13bd022ad Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Wed, 2 Mar 2016 20:45:16 +0100 >Subject: [PATCH 32/40] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 1 + > source4/torture/smb2/replay.c | 134 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 135 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 3796ac4..34d1f2d 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -210,6 +210,7 @@ > ^samba3.smb2.replay.replay-dhv2-oplock-lease > ^samba3.smb2.replay.replay-dhv2-lease1 > ^samba3.smb2.replay.replay-dhv2-lease2 >+^samba3.smb2.replay.replay-dhv2-lease3 > ^samba3.smb2.replay.replay-dhv2-lease-oplock > ^samba3.smb2.replay.replay3 > ^samba3.smb2.replay.replay4 >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index d541f7a..c32533b 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -1153,6 +1153,139 @@ done: > > /** > * Test durablity v2 create replay detection on single channel. >+ * create with a lease, and replay with a different lease key >+ */ >+static bool test_replay_dhv2_lease3(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle _h1; >+ struct smb2_handle *h1 = NULL; >+ struct smb2_handle _h2; >+ struct smb2_handle *h2 = NULL; >+ struct smb2_create io1, io2; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay2_lease2.dat"; >+ struct smb2_transport *transport = tree->session->transport; >+ uint32_t share_capabilities; >+ bool share_is_so; >+ uint32_t server_capabilities; >+ struct smb2_lease ls1, ls2; >+ uint64_t lease_key; >+ >+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "SMB 3.X Dialect family required for " >+ "replay tests\n"); >+ } >+ >+ server_capabilities = smb2cli_conn_server_capabilities(transport->conn); >+ if (!(server_capabilities & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli); >+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT; >+ >+ ZERO_STRUCT(break_info); >+ break_info.tctx = tctx; >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease " >+ "on Single Channel\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h1); >+ CHECK_VAL(break_info.count, 0); >+ >+ lease_key = random(); >+ >+ smb2_lease_create(&io1, &ls1, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RH")); >+ io1.in.durable_open = false; >+ io1.in.durable_open_v2 = true; >+ io1.in.persistent_open = false; >+ io1.in.create_guid = create_guid; >+ io1.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io1.out.durable_open, false); >+ CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key); >+ CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key); >+ if (share_is_so) { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("R")); >+ CHECK_VAL(io1.out.durable_open_v2, false); >+ CHECK_VAL(io1.out.timeout, 0); >+ } else { >+ CHECK_VAL(io1.out.lease_response.lease_state, >+ smb2_util_lease_state("RH")); >+ CHECK_VAL(io1.out.durable_open_v2, true); >+ CHECK_VAL(io1.out.timeout, io1.in.timeout); >+ } >+ _h1 = io1.out.file.handle; >+ h1 = &_h1; >+ >+ /* >+ * Upgrade the lease to RWH >+ */ >+ smb2_lease_create(&io2, &ls2, false /* dir */, fname, >+ lease_key, smb2_util_lease_state("RHW")); >+ io2.in.durable_open = false; >+ io2.in.durable_open_v2 = true; >+ io2.in.persistent_open = false; >+ io2.in.create_guid = GUID_random(); /* new guid... */ >+ io2.in.timeout = UINT32_MAX; >+ >+ status = smb2_create(tree, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ _h2 = io2.out.file.handle; >+ h2 = &_h2; >+ >+ /* >+ * Replay Durable V2 Create on single channel. >+ * use a different lease key. >+ */ >+ >+ smb2_lease_create(&io1, &ls1, false /* dir */, fname, >+ random() /* lease key */, >+ smb2_util_lease_state("RH")); >+ io1.in.durable_open = false; >+ io1.in.durable_open_v2 = true; >+ io1.in.persistent_open = false; >+ io1.in.create_guid = create_guid; >+ io1.in.timeout = UINT32_MAX; >+ >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ status = smb2_create(tree, mem_ctx, &io1); >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); >+ >+done: >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ >+ if (h1 != NULL) { >+ smb2_util_close(tree, *h1); >+ } >+ if (h2 != NULL) { >+ smb2_util_close(tree, *h2); >+ } >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+/** >+ * Test durablity v2 create replay detection on single channel. > * Do the original create with a lease, and do the replay > * with an oplock. > */ >@@ -1836,6 +1969,7 @@ struct torture_suite *torture_smb2_replay_init(void) > torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2", test_replay_dhv2_lease2); >+ torture_suite_add_1smb2_test(suite, "replay-dhv2-lease3", test_replay_dhv2_lease3); > torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock", test_replay_dhv2_lease_oplock); > torture_suite_add_1smb2_test(suite, "replay3", test_replay3); > torture_suite_add_1smb2_test(suite, "replay4", test_replay4); >-- >2.5.0 > > >From 94df8f6f2761f3c47e1959ff8982a0d4336a2c79 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Wed, 24 Feb 2016 15:53:57 +0100 >Subject: [PATCH 33/40] smbd:smb2: allow the REPLAY_OPERATION flag for SMB3+ > requests > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Michael Adam <obnox@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smb2_server.c | 3 +++ > 1 file changed, 3 insertions(+) > >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); > } >-- >2.5.0 > > >From 86c6d42c07f7754ccecdf2ded9423928df3292ef Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Fri, 26 Feb 2016 13:44:13 +0100 >Subject: [PATCH 34/40] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/librpc/idl/smbXsrv.idl | 6 ++++++ > 1 file changed, 6 insertions(+) > >diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl >index fe86545..c55ca31 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,7 @@ interface smbXsrv > NTSTATUS status; > NTTIME idle_time; > [ignore] files_struct *compat; >+ smbXsrv_open_flags flags; > } smbXsrv_open; > > typedef union { >-- >2.5.0 > > >From 214cb28c074ea4471465d7f4a28a101bd6aff2f7 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Wed, 24 Feb 2016 00:23:15 +0100 >Subject: [PATCH 35/40] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smbXsrv_open.c | 114 +++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 112 insertions(+), 2 deletions(-) > >diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index ee35f2d..d020817 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,24 @@ 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_recreate(struct smbXsrv_connection *conn, >-- >2.5.0 > > >From 76b93771cc08e8517569f0b4229083772dc3c20e Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Fri, 26 Feb 2016 13:53:25 +0100 >Subject: [PATCH 36/40] smb2:create: create replay cache when request has a > create_guid > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smb2_create.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > >diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c >index 7917d42..6f01c39 100644 >--- a/source3/smbd/smb2_create.c >+++ b/source3/smbd/smb2_create.c >@@ -668,6 +668,7 @@ 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; > #if 0 > struct smb2_create_blob *svhdx = NULL; > #endif >@@ -804,6 +805,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; >@@ -1154,6 +1161,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 " >-- >2.5.0 > > >From 358beac011c007b070fe6b144c518bb4253283d2 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sat, 27 Feb 2016 03:23:27 +0100 >Subject: [PATCH 37/40] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/globals.h | 4 ++++ > source3/smbd/smbXsrv_open.c | 41 +++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 45 insertions(+) > >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/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index d020817..a7cea18 100644 >--- a/source3/smbd/smbXsrv_open.c >+++ b/source3/smbd/smbXsrv_open.c >@@ -1283,6 +1283,47 @@ NTSTATUS smb2srv_open_lookup(struct smbXsrv_connection *conn, > 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, > struct auth_session_info *session_info, > uint64_t persistent_id, >-- >2.5.0 > > >From f6b22942f32dacfb030b5d3d1888705aee0f6f4e Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 29 Feb 2016 02:11:26 +0100 >Subject: [PATCH 38/40] smbXsrv.idl: add create_action to smbXsrv_open > >Needed for create replay. > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > source3/librpc/idl/smbXsrv.idl | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl >index c55ca31..4c6895a 100644 >--- a/source3/librpc/idl/smbXsrv.idl >+++ b/source3/librpc/idl/smbXsrv.idl >@@ -469,6 +469,7 @@ interface smbXsrv > NTTIME idle_time; > [ignore] files_struct *compat; > smbXsrv_open_flags flags; >+ uint32 create_action; > } smbXsrv_open; > > typedef union { >-- >2.5.0 > > >From 2a484b972702b9b2e7d65b1a287acebaf53f9a2d Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sun, 28 Feb 2016 02:32:36 +0100 >Subject: [PATCH 39/40] smbd:smb2: implement create replay > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >--- > selftest/knownfail | 10 ----- > source3/smbd/smb2_create.c | 95 +++++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 89 insertions(+), 16 deletions(-) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 34d1f2d..1ac99d4 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -202,16 +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.replay-commands >-^samba3.smb2.replay.replay-regular >-^samba3.smb2.replay.replay-dhv2-oplock1 >-^samba3.smb2.replay.replay-dhv2-oplock2 >-^samba3.smb2.replay.replay-dhv2-oplock3 >-^samba3.smb2.replay.replay-dhv2-oplock-lease >-^samba3.smb2.replay.replay-dhv2-lease1 >-^samba3.smb2.replay.replay-dhv2-lease2 >-^samba3.smb2.replay.replay-dhv2-lease3 >-^samba3.smb2.replay.replay-dhv2-lease-oplock > ^samba3.smb2.replay.replay3 > ^samba3.smb2.replay.replay4 > ^samba3.smb2.lock.*replay >diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c >index 6f01c39..d50b20c 100644 >--- a/source3/smbd/smb2_create.c >+++ b/source3/smbd/smb2_create.c >@@ -475,6 +475,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, > 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; >@@ -779,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); >@@ -823,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) { >@@ -918,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 */ >@@ -930,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); > >@@ -1142,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, >@@ -1152,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; >@@ -1189,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; >@@ -1261,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); >@@ -1273,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); > >-- >2.5.0 > > >From 42423a0dde80f58062a41fec7f8386bf9a401972 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Thu, 3 Mar 2016 09:27:42 +0100 >Subject: [PATCH 40/40] smbd:smb2: move op variable into scope of use in > smb2_create_send > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >--- > source3/smbd/smb2_create.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c >index d50b20c..17bddc1 100644 >--- a/source3/smbd/smb2_create.c >+++ b/source3/smbd/smb2_create.c >@@ -474,7 +474,6 @@ 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))) { >@@ -670,6 +669,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, > 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 >-- >2.5.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 11779
:
11904
|
11906