The Samba-Bugzilla – Attachment 12082 Details for
Bug 11809
SMB3 multichannel implementation is missing channel sequence number verification
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Updated patch for v4-4-test.
bug-11809.v4-4-test.patch (text/plain), 33.07 KB, created by
Michael Adam
on 2016-05-06 14:57:54 UTC
(
hide
)
Description:
Updated patch for v4-4-test.
Filename:
MIME Type:
Creator:
Michael Adam
Created:
2016-05-06 14:57:54 UTC
Size:
33.07 KB
patch
obsolete
>From efd8a68e9c3c3a524417b1bf20aaf8791dd069aa Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Wed, 27 Jan 2016 16:18:25 +0100 >Subject: [PATCH 01/10] s3:smbXsrv.idl: add 8 byte channel_sequence number and > request counters to IDL. > >Guenther > >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 31f33a3f3996a5fff9833540c8227600f4aa2a55) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > source3/librpc/idl/smbXsrv.idl | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl >index 4c6895a..1bfa51e 100644 >--- a/source3/librpc/idl/smbXsrv.idl >+++ b/source3/librpc/idl/smbXsrv.idl >@@ -430,6 +430,7 @@ interface smbXsrv > uint32 durable_timeout_msec; > boolean8 durable; > DATA_BLOB backend_cookie; >+ hyper channel_sequence; > } smbXsrv_open_global0; > > typedef union { >@@ -470,6 +471,8 @@ interface smbXsrv > [ignore] files_struct *compat; > smbXsrv_open_flags flags; > uint32 create_action; >+ hyper request_count; >+ hyper pre_request_count; > } smbXsrv_open; > > typedef union { >-- >2.5.5 > > >From d8a75dcc069126790c8b3e1d76261365f7331775 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Wed, 24 Feb 2016 15:51:14 +0100 >Subject: [PATCH 02/10] smbd:smb2: add a modify flag to dispatch table > >This indicates that an operation is a modifying operation. >Some parts of the upcoming channel sequence number logic >only applies to modify operations. > >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> >(cherry picked from commit 088468195b7f7f04eab0ce6fb928bda1c703e2fa) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > source3/smbd/smb2_server.c | 4 ++++ > 1 file changed, 4 insertions(+) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index 68d637e..7b6d8d6 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -46,6 +46,7 @@ static const struct smbd_smb2_dispatch_table { > bool as_root; > uint16_t fileid_ofs; > bool allow_invalid_fileid; >+ bool modify; > } smbd_smb2_table[] = { > #define _OP(o) .opcode = o, .name = #o > { >@@ -98,6 +99,7 @@ static const struct smbd_smb2_dispatch_table { > .need_session = true, > .need_tcon = true, > .fileid_ofs = 0x10, >+ .modify = true, > },{ > _OP(SMB2_OP_LOCK), > .need_session = true, >@@ -109,6 +111,7 @@ static const struct smbd_smb2_dispatch_table { > .need_tcon = true, > .fileid_ofs = 0x08, > .allow_invalid_fileid = true, >+ .modify = true, > },{ > _OP(SMB2_OP_CANCEL), > .as_root = true, >@@ -135,6 +138,7 @@ static const struct smbd_smb2_dispatch_table { > .need_session = true, > .need_tcon = true, > .fileid_ofs = 0x10, >+ .modify = true, > },{ > _OP(SMB2_OP_BREAK), > .need_session = true, >-- >2.5.5 > > >From 6b9830dd5649be65fcc8615e7cac4451c250f785 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 15 Mar 2016 12:36:59 +0100 >Subject: [PATCH 03/10] smbd:smb2: add request_counters_updated to the > smbd_smb2_request struct > >This will be used to keep track of whether the outstanding request >counters have been updated in the dispatch, so that the reply >code can act accordingly. > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit ae6967ea3e39a1a5401be4a4c969b467dd22dce4) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > source3/smbd/globals.h | 7 +++++++ > 1 file changed, 7 insertions(+) > >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index 15f29a8..9e3e95c 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -727,6 +727,13 @@ struct smbd_smb2_request { > struct files_struct *compat_chain_fsp; > > /* >+ * Keep track of whether the outstanding request counters >+ * had been updated in dispatch, so that they need to be >+ * adapted again in reply. >+ */ >+ bool request_counters_updated; >+ >+ /* > * The sub request for async backend calls. > * This is used for SMB2 Cancel. > */ >-- >2.5.5 > > >From 0f0732d4ac20ffc14e008291a67deaf529ae7f97 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Wed, 24 Feb 2016 15:54:41 +0100 >Subject: [PATCH 04/10] smbd:smb2: implement channel sequence checks and > request counters in dispatch > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> >Pair-Programmed-With: Guenther Deschner <gd@samba.org> > >Signed-off-by: Michael Adam <obnox@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 71d2b190646bdf5fce65a776dfe6873da8d82479) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > source3/smbd/smb2_server.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 120 insertions(+) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index 7b6d8d6..01892e1 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -2111,6 +2111,121 @@ bool smbXsrv_is_partially_signed(uint8_t signing_flags) > (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET)); > } > >+static NTSTATUS smbd_smb2_request_dispatch_update_counts( >+ struct smbd_smb2_request *req, >+ bool modify_call) >+{ >+ struct smbXsrv_connection *xconn = req->xconn; >+ const uint8_t *inhdr; >+ uint16_t channel_sequence; >+ uint32_t flags; >+ int cmp; >+ struct smbXsrv_open *op; >+ bool update_open = false; >+ NTSTATUS status = NT_STATUS_OK; >+ >+ req->request_counters_updated = false; >+ >+ if (xconn->protocol < PROTOCOL_SMB2_22) { >+ return NT_STATUS_OK; >+ } >+ >+ if (req->compat_chain_fsp == NULL) { >+ return NT_STATUS_OK; >+ } >+ >+ op = req->compat_chain_fsp->op; >+ if (op == NULL) { >+ return NT_STATUS_OK; >+ } >+ >+ inhdr = SMBD_SMB2_IN_HDR_PTR(req); >+ flags = IVAL(inhdr, SMB2_HDR_FLAGS); >+ channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE); >+ >+ cmp = channel_sequence - op->global->channel_sequence; >+ >+ if (abs(cmp) > INT16_MAX) { >+ /* >+ * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number: >+ * >+ * If the channel sequence number of the request and the one >+ * known to the server are not equal, the channel sequence >+ * number and outstanding request counts are only updated >+ * "... if the unsigned difference using 16-bit arithmetic >+ * between ChannelSequence and Open.ChannelSequence is less than >+ * or equal to 0x7FFF ...". >+ * Otherwise, an error is returned for the modifying >+ * calls write, set_info, and ioctl. >+ * >+ * There are currently two issues with the description: >+ * >+ * * For the other calls, the document seems to imply >+ * that processing continues without adapting the >+ * counters (if the sequence numbers are not equal). >+ * >+ * TODO: This needs clarification! >+ * >+ * * Also, the behaviour if the difference is larger >+ * than 0x7FFF is not clear. The document seems to >+ * imply that if such a difference is reached, >+ * the server starts to ignore the counters or >+ * in the case of the modifying calls, return errors. >+ * >+ * TODO: This needs clarification! >+ * >+ * At this point Samba tries to be a little more >+ * clever than the description in the MS-SMB2 document >+ * by heuristically detecting and properly treating >+ * a 16 bit overflow of the client-submitted sequence >+ * number: >+ * >+ * If the stored channel squence number is more than >+ * 0x7FFF larger than the one from the request, then >+ * the client-provided sequence number has likely >+ * overflown. We treat this case as valid instead >+ * of as failure. >+ * >+ * The MS-SMB2 behaviour would be setting cmp = -1. >+ */ >+ cmp *= -1; >+ } >+ >+ if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) { >+ if (cmp == 0) { >+ op->request_count += 1; >+ req->request_counters_updated = true; >+ } else if (cmp > 0) { >+ op->pre_request_count += op->request_count; >+ op->request_count = 1; >+ op->global->channel_sequence = channel_sequence; >+ update_open = true; >+ req->request_counters_updated = true; >+ } else if (modify_call) { >+ return NT_STATUS_FILE_NOT_AVAILABLE; >+ } >+ } else { >+ if (cmp == 0 && op->pre_request_count == 0) { >+ op->request_count += 1; >+ req->request_counters_updated = true; >+ } else if (cmp > 0 && op->pre_request_count == 0) { >+ op->pre_request_count += op->request_count; >+ op->request_count = 1; >+ op->global->channel_sequence = channel_sequence; >+ update_open = true; >+ req->request_counters_updated = true; >+ } else if (modify_call) { >+ return NT_STATUS_FILE_NOT_AVAILABLE; >+ } >+ } >+ >+ if (update_open) { >+ status = smbXsrv_open_update(op); >+ } >+ >+ return status; >+} >+ > NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) > { > struct smbXsrv_connection *xconn = req->xconn; >@@ -2408,6 +2523,11 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) > } > } > >+ status = smbd_smb2_request_dispatch_update_counts(req, call->modify); >+ if (!NT_STATUS_IS_OK(status)) { >+ return smbd_smb2_request_error(req, status); >+ } >+ > if (call->as_root) { > SMB_ASSERT(call->fileid_ofs == 0); > /* This call needs to be run as root */ >-- >2.5.5 > > >From 9be88c8fd8779813cbef961b84751b1a079a2081 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 23 Feb 2016 20:54:34 +0100 >Subject: [PATCH 05/10] smbd:smb2: update outstanding request counters before > sending a reply > >This is part of the channel sequence number treatment of multi-channel. > >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: Jeremy Allison <jra@samba.org> >(cherry picked from commit 7dbb1707d96e39bed8898db08339d3b2d768c87c) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > source3/smbd/smb2_server.c | 37 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 37 insertions(+) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index 01892e1..ae125df 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -2676,6 +2676,40 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) > return return_value; > } > >+static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req) >+{ >+ struct smbXsrv_connection *xconn = req->xconn; >+ const uint8_t *inhdr; >+ uint16_t channel_sequence; >+ struct smbXsrv_open *op; >+ >+ if (!req->request_counters_updated) { >+ return; >+ } >+ >+ if (xconn->protocol < PROTOCOL_SMB2_22) { >+ return; >+ } >+ >+ if (req->compat_chain_fsp == NULL) { >+ return; >+ } >+ >+ op = req->compat_chain_fsp->op; >+ if (op == NULL) { >+ return; >+ } >+ >+ inhdr = SMBD_SMB2_IN_HDR_PTR(req); >+ channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE); >+ >+ if (op->global->channel_sequence == channel_sequence) { >+ op->request_count -= 1; >+ } else { >+ op->pre_request_count -= 1; >+ } >+} >+ > static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) > { > struct smbXsrv_connection *xconn = req->xconn; >@@ -2689,6 +2723,9 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) > req->subreq = NULL; > TALLOC_FREE(req->async_te); > >+ /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */ >+ smbd_smb2_request_reply_update_counts(req); >+ > if (req->do_encryption && > (firsttf->iov_len == 0) && > (req->first_key.length == 0) && >-- >2.5.5 > > >From ce5a7e80205c45fae7ec14606a683dd068ad1e7f Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Sat, 27 Feb 2016 14:02:02 +0100 >Subject: [PATCH 06/10] smbd:smb2: add some asserts before decrementing the > counters > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit f81f3a2d78832258b09bcc63d5cce2b4594cbbc8) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > source3/smbd/smb2_server.c | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index ae125df..8a4aa96 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -2704,8 +2704,10 @@ static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req) > channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE); > > if (op->global->channel_sequence == channel_sequence) { >+ SMB_ASSERT(op->request_count > 0); > op->request_count -= 1; > } else { >+ SMB_ASSERT(op->pre_request_count > 0); > op->pre_request_count -= 1; > } > } >-- >2.5.5 > > >From 01b961d46884856414bf4117b4f5cf39786bed5e Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Tue, 1 Mar 2016 15:15:10 +0100 >Subject: [PATCH 07/10] libcli:smb:smbXcli_base: add > smb2cli_session_current_channel_sequence() call. > >Guenther > >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit ccda60ed9b33bb22ec2e162401a949aeaa631c8d) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > libcli/smb/smbXcli_base.c | 5 +++++ > libcli/smb/smbXcli_base.h | 1 + > 2 files changed, 6 insertions(+) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index faf74ca..4332374 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -5522,6 +5522,11 @@ uint16_t smb2cli_session_reset_channel_sequence(struct smbXcli_session *session, > return prev_cs; > } > >+uint16_t smb2cli_session_current_channel_sequence(struct smbXcli_session *session) >+{ >+ return session->smb2->channel_sequence; >+} >+ > void smb2cli_session_start_replay(struct smbXcli_session *session) > { > session->smb2->replay_active = true; >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index 8b9851b..16c8848 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -413,6 +413,7 @@ void smb2cli_session_set_id_and_flags(struct smbXcli_session *session, > void smb2cli_session_increment_channel_sequence(struct smbXcli_session *session); > uint16_t smb2cli_session_reset_channel_sequence(struct smbXcli_session *session, > uint16_t channel_sequence); >+uint16_t smb2cli_session_current_channel_sequence(struct smbXcli_session *session); > void smb2cli_session_start_replay(struct smbXcli_session *session); > void smb2cli_session_stop_replay(struct smbXcli_session *session); > NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session, >-- >2.5.5 > > >From ad29a33fe582618141a3e67bdc2981856fd67094 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Thu, 25 Feb 2016 11:15:06 +0100 >Subject: [PATCH 08/10] torture:smb2: add test for checking sequence number > wrap around. > >Guenther > >Signed-off-by: Guenther Deschner <gd@samba.org> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 2b799880b91f2ee44531644c62916f9a50531d04) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > selftest/knownfail | 1 + > source4/torture/smb2/replay.c | 266 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 267 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 1678cd0..997d29c 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -211,6 +211,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.channel-sequence > ^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 c32533b..8388837 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -1428,6 +1428,271 @@ done: > return ret; > } > >+static bool test_channel_sequence_table(struct torture_context *tctx, >+ struct smb2_tree *tree, >+ bool do_replay, >+ uint16_t opcode) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_handle handle; >+ struct smb2_handle *phandle = NULL; >+ struct smb2_create io; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\channel_sequence.dat"; >+ uint16_t csn = 0; >+ uint16_t limit = UINT16_MAX - 0x7fff; >+ int i; >+ struct { >+ uint16_t csn; >+ bool csn_rand_low; >+ bool csn_rand_high; >+ NTSTATUS expected_status; >+ } tests[] = { >+ { >+ .csn = 0, >+ .expected_status = NT_STATUS_OK, >+ },{ >+ .csn = 0x7fff + 1, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = 0x7fff + 2, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = -1, >+ .csn_rand_high = true, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = 0xffff, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = 0x7fff, >+ .expected_status = NT_STATUS_OK, >+ },{ >+ .csn = 0x7ffe, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = 0, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = -1, >+ .csn_rand_low = true, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = 0x7fff + 1, >+ .expected_status = NT_STATUS_OK, >+ },{ >+ .csn = 0xffff, >+ .expected_status = NT_STATUS_OK, >+ },{ >+ .csn = 0, >+ .expected_status = NT_STATUS_OK, >+ },{ >+ .csn = 1, >+ .expected_status = NT_STATUS_OK, >+ },{ >+ .csn = 0, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ },{ >+ .csn = 1, >+ .expected_status = NT_STATUS_OK, >+ },{ >+ .csn = 0xffff, >+ .expected_status = NT_STATUS_FILE_NOT_AVAILABLE, >+ } >+ }; >+ >+ smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0); >+ >+ csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli); >+ torture_comment(tctx, "Testing create with channel sequence number: 0x%04x\n", csn); >+ >+ 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.create_guid = create_guid; >+ io.in.timeout = UINT32_MAX; >+ >+ torture_assert_ntstatus_ok_goto(tctx, >+ smb2_create(tree, mem_ctx, &io), >+ ret, done, "failed to call smb2_create"); >+ >+ handle = io.out.file.handle; >+ phandle = &handle; >+ >+ for (i=0; i <ARRAY_SIZE(tests); i++) { >+ >+ const char *opstr = ""; >+ union smb_fileinfo qfinfo; >+ >+ csn = tests[i].csn; >+ >+ if (tests[i].csn_rand_low) { >+ csn = rand() % limit; >+ } else if (tests[i].csn_rand_high) { >+ csn = rand() % limit + 0x7fff; >+ } >+ >+ switch (opcode) { >+ case SMB2_OP_WRITE: >+ opstr = "write"; >+ break; >+ case SMB2_OP_IOCTL: >+ opstr = "ioctl"; >+ break; >+ case SMB2_OP_SETINFO: >+ opstr = "setinfo"; >+ break; >+ default: >+ break; >+ } >+ >+ smb2cli_session_reset_channel_sequence(tree->session->smbXcli, csn); >+ csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli); >+ >+ torture_comment(tctx, "Testing %s (replay: %s) with CSN 0x%04x, expecting: %s\n", >+ opstr, do_replay ? "true" : "false", csn, >+ nt_errstr(tests[i].expected_status)); >+ >+ if (do_replay) { >+ smb2cli_session_start_replay(tree->session->smbXcli); >+ } >+ >+ switch (opcode) { >+ case SMB2_OP_WRITE: { >+ DATA_BLOB blob = data_blob_talloc(tctx, NULL, 255); >+ >+ generate_random_buffer(blob.data, blob.length); >+ >+ status = smb2_util_write(tree, handle, blob.data, 0, blob.length); >+ if (NT_STATUS_IS_OK(status)) { >+ struct smb2_read rd; >+ >+ rd = (struct smb2_read) { >+ .in.file.handle = handle, >+ .in.length = blob.length, >+ .in.offset = 0 >+ }; >+ >+ torture_assert_ntstatus_ok_goto(tctx, >+ smb2_read(tree, tree, &rd), >+ ret, done, "failed to read after write"); >+ >+ torture_assert_data_blob_equal(tctx, >+ rd.out.data, blob, >+ "read/write mismatch"); >+ } >+ break; >+ } >+ case SMB2_OP_IOCTL: { >+ union smb_ioctl ioctl; >+ ioctl = (union smb_ioctl) { >+ .smb2.level = RAW_IOCTL_SMB2, >+ .smb2.in.file.handle = handle, >+ .smb2.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID, >+ .smb2.in.max_response_size = 64, >+ .smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL >+ }; >+ status = smb2_ioctl(tree, mem_ctx, &ioctl.smb2); >+ break; >+ } >+ case SMB2_OP_SETINFO: { >+ union smb_setfileinfo sfinfo; >+ ZERO_STRUCT(sfinfo); >+ sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION; >+ sfinfo.generic.in.file.handle = handle; >+ sfinfo.position_information.in.position = 0x1000; >+ status = smb2_setinfo_file(tree, &sfinfo); >+ break; >+ } >+ default: >+ break; >+ } >+ >+ qfinfo = (union smb_fileinfo) { >+ .generic.level = RAW_SFILEINFO_POSITION_INFORMATION, >+ .generic.in.file.handle = handle >+ }; >+ >+ torture_assert_ntstatus_ok_goto(tctx, >+ smb2_getinfo_file(tree, mem_ctx, &qfinfo), >+ ret, done, "failed to read after write"); >+ >+ if (do_replay) { >+ smb2cli_session_stop_replay(tree->session->smbXcli); >+ } >+ >+ torture_assert_ntstatus_equal_goto(tctx, >+ status, tests[i].expected_status, >+ ret, done, "got unexpected failure code"); >+ >+ } >+done: >+ if (phandle != NULL) { >+ smb2_util_close(tree, *phandle); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ return ret; >+} >+ >+static bool test_channel_sequence(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ bool ret = true; >+ const char *fname = BASEDIR "\\channel_sequence.dat"; >+ struct smb2_transport *transport1 = tree->session->transport; >+ struct smb2_handle handle; >+ uint32_t server_capabilities; >+ uint16_t opcodes[] = { SMB2_OP_WRITE, SMB2_OP_IOCTL, SMB2_OP_SETINFO }; >+ int i; >+ >+ 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( >+ tree->session->transport->conn); >+ if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) { >+ torture_skip(tctx, >+ "Server does not support multi-channel."); >+ } >+ >+ torture_comment(tctx, "Testing channel sequence numbers\n"); >+ >+ torture_assert_ntstatus_ok_goto(tctx, >+ torture_smb2_testdir(tree, BASEDIR, &handle), >+ ret, done, "failed to setup test directory"); >+ >+ smb2_util_close(tree, handle); >+ smb2_util_unlink(tree, fname); >+ >+ for (i=0; i <ARRAY_SIZE(opcodes); i++) { >+ torture_assert(tctx, >+ test_channel_sequence_table(tctx, tree, false, opcodes[i]), >+ "failed to test CSN without replay flag"); >+ torture_assert(tctx, >+ test_channel_sequence_table(tctx, tree, true, opcodes[i]), >+ "failed to test CSN with replay flag"); >+ } >+ >+done: >+ >+ smb2_util_unlink(tree, fname); >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ > /** > * Test Durablity V2 Create Replay Detection on Multi Channel > */ >@@ -1971,6 +2236,7 @@ struct torture_suite *torture_smb2_replay_init(void) > 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, "channel-sequence", test_channel_sequence); > 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.5 > > >From 09633984801ee04d97a200ae18a4300adf926e3b Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> >Date: Wed, 24 Feb 2016 19:23:21 +0100 >Subject: [PATCH 09/10] lib/torture: add torture_assert_u64_not_equal_goto > macro >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >Guenther > >Signed-off-by: Günther Deschner <gd@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit c5c3f91c6fd1ac3282d2fa27e262af097f0adfca) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > lib/torture/torture.h | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > >diff --git a/lib/torture/torture.h b/lib/torture/torture.h >index 356922a..e710873 100644 >--- a/lib/torture/torture.h >+++ b/lib/torture/torture.h >@@ -479,6 +479,18 @@ void torture_result(struct torture_context *test, > } \ > } while(0) > >+#define torture_assert_u64_not_equal_goto(torture_ctx,got,not_expected,ret,label,cmt)\ >+ do { uint64_t __got = (got), __not_expected = (not_expected); \ >+ if (__got == __not_expected) { \ >+ torture_result(torture_ctx, TORTURE_FAIL, \ >+ __location__": "#got" was %llu (0x%llX), expected a different number: %s", \ >+ (unsigned long long)__got, (unsigned long long)__got, \ >+ cmt); \ >+ ret = false; \ >+ goto label; \ >+ } \ >+ } while(0) >+ > #define torture_assert_errno_equal(torture_ctx,expected,cmt)\ > do { int __expected = (expected); \ > if (errno != __expected) { \ >-- >2.5.5 > > >From 75a45cbb1108fff094e7f9b442c6f49024efc65a Mon Sep 17 00:00:00 2001 >From: Anubhav Rakshit <anubhav.rakshit@gmail.com> >Date: Thu, 30 Oct 2014 13:20:57 +0530 >Subject: [PATCH 10/10] torture:smb2: Add test replay6 to verify Error Codes > for DurableHandleReqV2 replay > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> >Pair-Programmed-With: Guenther Deschner <gd@samba.org> >Pair-Programmed-With: Michael Adam <obnox@samba.org> > >Signed-off-by: Anubhav Rakshit <anubhav.rakshit@gmail.com> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Signed-off-by: Guenther Deschner <gd@samba.org> >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit e095a61c4b36e71b03d8afc724da09c91603a29b) > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11809 >--- > source4/torture/smb2/replay.c | 211 +++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 209 insertions(+), 2 deletions(-) > >diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c >index 8388837..91bb568 100644 >--- a/source4/torture/smb2/replay.c >+++ b/source4/torture/smb2/replay.c >@@ -94,7 +94,7 @@ > > #define BASEDIR "replaytestdir" > >-static struct { >+struct break_info { > struct torture_context *tctx; > struct smb2_handle handle; > uint8_t level; >@@ -102,7 +102,16 @@ static struct { > int count; > int failures; > NTSTATUS failure_status; >-} break_info; >+}; >+ >+static struct break_info break_info; >+ >+static void torture_reset_break_info(struct torture_context *tctx, >+ struct break_info *r) >+{ >+ ZERO_STRUCTP(r); >+ r->tctx = tctx; >+} > > static void torture_oplock_ack_callback(struct smb2_request *req) > { >@@ -163,6 +172,61 @@ static bool torture_oplock_ack_handler(struct smb2_transport *transport, > } > > /** >+ * Timer handler function notifies the registering function that time is up >+ */ >+static void timeout_cb(struct tevent_context *ev, >+ struct tevent_timer *te, >+ struct timeval current_time, >+ void *private_data) >+{ >+ bool *timesup = (bool *)private_data; >+ *timesup = true; >+ return; >+} >+ >+/** >+ * Wait a short period of time to receive a single oplock break request >+ */ >+static void torture_wait_for_oplock_break(struct torture_context *tctx) >+{ >+ TALLOC_CTX *tmp_ctx = talloc_new(NULL); >+ struct tevent_timer *te = NULL; >+ struct timeval ne; >+ bool timesup = false; >+ int old_count = break_info.count; >+ >+ /* Wait .1 seconds for an oplock break */ >+ ne = tevent_timeval_current_ofs(0, 100000); >+ >+ te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up); >+ if (te == NULL) { >+ torture_comment(tctx, "Failed to wait for an oplock break. " >+ "test results may not be accurate."); >+ goto done; >+ } >+ >+ while (!timesup && break_info.count < old_count + 1) { >+ if (tevent_loop_once(tctx->ev) != 0) { >+ torture_comment(tctx, "Failed to wait for an oplock " >+ "break. test results may not be " >+ "accurate."); >+ goto done; >+ } >+ } >+ >+done: >+ /* >+ * We don't know if the timed event fired and was freed, we received >+ * our oplock break, or some other event triggered the loop. Thus, >+ * we create a tmp_ctx to be able to safely free/remove the timed >+ * event in all 3 cases. >+ */ >+ talloc_free(tmp_ctx); >+ >+ return; >+} >+ >+/** > * 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. > */ >@@ -2221,6 +2285,148 @@ done: > return ret; > } > >+ >+/** >+ * Test Error Codes when a DurableHandleReqV2 with matching CreateGuid is >+ * re-sent with or without SMB2_FLAGS_REPLAY_OPERATION >+ */ >+static bool test_replay6(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; >+ union smb_fileinfo qfinfo; >+ struct GUID create_guid = GUID_random(); >+ bool ret = true; >+ const char *fname = BASEDIR "\\replay6.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"); >+ } >+ >+ torture_reset_break_info(tctx, &break_info); >+ tree->session->transport->oplock.handler = torture_oplock_ack_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ torture_comment(tctx, "Error Codes for DurableHandleReqV2 Replay\n"); >+ smb2_util_unlink(tree, fname); >+ status = torture_smb2_testdir(tree, BASEDIR, &_h); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ smb2_util_close(tree, _h); >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ torture_reset_break_info(tctx, &break_info); >+ >+ 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; >+ >+ 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.oplock_level, smb2_util_oplock_level("b")); >+ CHECK_VAL(io.out.durable_open, false); >+ CHECK_VAL(io.out.durable_open_v2, true); >+ >+ io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; >+ io.in.create_disposition = NTCREATEX_DISP_OPEN; >+ 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_OK); >+ CHECK_CREATE_OUT(&io, &ref1); >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ torture_reset_break_info(tctx, &break_info); >+ >+ qfinfo = (union smb_fileinfo) { >+ .generic.level = RAW_SFILEINFO_POSITION_INFORMATION, >+ .generic.in.file.handle = *h >+ }; >+ torture_comment(tctx, "Trying getinfo\n"); >+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VAL(qfinfo.position_information.out.position, 0); >+ >+ 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_OK); >+ torture_assert_u64_not_equal_goto(tctx, >+ io.out.file.handle.data[0], >+ ref1.out.file.handle.data[0], >+ ret, done, "data 0"); >+ torture_assert_u64_not_equal_goto(tctx, >+ io.out.file.handle.data[1], >+ ref1.out.file.handle.data[1], >+ ret, done, "data 1"); >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 1); >+ CHECK_VAL(break_info.level, smb2_util_oplock_level("s")); >+ torture_reset_break_info(tctx, &break_info); >+ >+ /* >+ * Resend the matching Durable V2 Create without >+ * SMB2_FLAGS_REPLAY_OPERATION. This triggers an oplock break and still >+ * gets NT_STATUS_DUPLICATE_OBJECTID >+ */ >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_DUPLICATE_OBJECTID); >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ torture_reset_break_info(tctx, &break_info); >+ >+ /* >+ * According to MS-SMB2 3.3.5.9.10 if Durable V2 Create is replayed and >+ * FileAttributes or CreateDisposition do not match the earlier Create >+ * request the Server fails request with >+ * NT_STATUS_INVALID_PARAMETER. But through this test we see that server >+ * does not really care about changed FileAttributes or >+ * CreateDisposition. >+ */ >+ io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; >+ io.in.create_disposition = NTCREATEX_DISP_OPEN; >+ 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_OK); >+ torture_assert_u64_not_equal_goto(tctx, >+ io.out.file.handle.data[0], >+ ref1.out.file.handle.data[0], >+ ret, done, "data 0"); >+ torture_assert_u64_not_equal_goto(tctx, >+ io.out.file.handle.data[1], >+ ref1.out.file.handle.data[1], >+ ret, done, "data 1"); >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ >+done: >+ if (h != NULL) { >+ smb2_util_close(tree, *h); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ smb2_deltree(tree, BASEDIR); >+ >+ talloc_free(tree); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ > struct torture_suite *torture_smb2_replay_init(void) > { > struct torture_suite *suite = >@@ -2240,6 +2446,7 @@ struct torture_suite *torture_smb2_replay_init(void) > 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); >+ torture_suite_add_1smb2_test(suite, "replay6", test_replay6); > > suite->description = talloc_strdup(suite, "SMB2 REPLAY tests"); > >-- >2.5.5 >
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
Flags:
obnox
:
review+
gd
:
review+
Actions:
View
Attachments on
bug 11809
:
11935
| 12082