summaryrefslogtreecommitdiffstats
path: root/source4/torture/smb2/session.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
commit4f5791ebd03eaec1c7da0865a383175b05102712 (patch)
tree8ce7b00f7a76baa386372422adebbe64510812d4 /source4/torture/smb2/session.c
parentInitial commit. (diff)
downloadsamba-upstream.tar.xz
samba-upstream.zip
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source4/torture/smb2/session.c')
-rw-r--r--source4/torture/smb2/session.c5564
1 files changed, 5564 insertions, 0 deletions
diff --git a/source4/torture/smb2/session.c b/source4/torture/smb2/session.c
new file mode 100644
index 0000000..e417008
--- /dev/null
+++ b/source4/torture/smb2/session.c
@@ -0,0 +1,5564 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ test suite for SMB2 session setups
+
+ Copyright (C) Michael Adam 2012
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "torture/torture.h"
+#include "torture/util.h"
+#include "torture/smb2/proto.h"
+#include "../libcli/smb/smbXcli_base.h"
+#include "lib/cmdline/cmdline.h"
+#include "auth/credentials/credentials.h"
+#include "auth/credentials/credentials_krb5.h"
+#include "libcli/security/security.h"
+#include "libcli/resolve/resolve.h"
+#include "lib/param/param.h"
+#include "lib/util/tevent_ntstatus.h"
+
+#define CHECK_CREATED(tctx, __io, __created, __attribute) \
+ do { \
+ torture_assert_int_equal(tctx, (__io)->out.create_action, \
+ NTCREATEX_ACTION_ ## __created, \
+ "out.create_action incorrect"); \
+ torture_assert_int_equal(tctx, (__io)->out.size, 0, \
+ "out.size incorrect"); \
+ torture_assert_int_equal(tctx, (__io)->out.file_attr, \
+ (__attribute), \
+ "out.file_attr incorrect"); \
+ torture_assert_int_equal(tctx, (__io)->out.reserved2, 0, \
+ "out.reserverd2 incorrect"); \
+ } while(0)
+
+#define WAIT_FOR_ASYNC_RESPONSE(req) \
+ while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
+ if (tevent_loop_once(tctx->ev) != 0) { \
+ break; \
+ } \
+ }
+
+/**
+ * basic test for doing a session reconnect
+ */
+bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_handle _h2;
+ struct smb2_handle *h2 = NULL;
+ struct smb2_create io1, io2;
+ uint64_t previous_session_id;
+ bool ret = true;
+ struct smb2_tree *tree2 = NULL;
+ union smb_fileinfo qfinfo;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* disconnect, reconnect and then do durable reopen */
+ previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
+
+ torture_assert_goto(tctx, torture_smb2_connection_ext(tctx, previous_session_id,
+ &tree->session->transport->options, &tree2),
+ ret, done,
+ "session reconnect failed\n");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_USER_SESSION_DELETED,
+ ret, done, "smb2_getinfo_file "
+ "returned unexpected status");
+ h1 = NULL;
+
+ smb2_oplock_create_share(&io2, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree2, mem_ctx, &io2);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+
+ CHECK_CREATED(tctx, &io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+ _h2 = io2.out.file.handle;
+ h2 = &_h2;
+
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+ if (h2 != NULL) {
+ smb2_util_close(tree2, *h2);
+ }
+
+ if (tree2 != NULL) {
+ smb2_util_unlink(tree2, fname);
+ }
+ smb2_util_unlink(tree, fname);
+
+ talloc_free(tree);
+ talloc_free(tree2);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/**
+ * basic test for doing a session reconnect on one connection
+ */
+bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ uint64_t previous_session_id;
+ bool ret = true;
+ struct smb2_session *session2 = NULL;
+ union smb_fileinfo qfinfo;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+ io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* disconnect, reconnect and then do durable reopen */
+ previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
+
+ torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
+ previous_session_id, tctx, &session2),
+ "session reconnect (on the same connection) failed");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_USER_SESSION_DELETED,
+ ret, done, "smb2_getinfo_file "
+ "returned unexpected status");
+ h1 = NULL;
+
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ talloc_free(tree);
+ talloc_free(session2);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ bool ret = true;
+ union smb_fileinfo qfinfo;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ status = smb2_session_setup_spnego(tree->session,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ status = smb2_session_setup_spnego(tree->session,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ smb2_util_unlink(tree, fname);
+
+ talloc_free(tree);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ bool ret = true;
+ union smb_fileinfo qfinfo;
+ struct cli_credentials *anon_creds = NULL;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* re-authenticate as anonymous */
+
+ anon_creds = cli_credentials_init_anon(mem_ctx);
+ torture_assert(tctx, (anon_creds != NULL), "talloc error");
+
+ status = smb2_session_setup_spnego(tree->session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /* re-authenticate as original user again */
+
+ status = smb2_session_setup_spnego(tree->session,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ smb2_util_unlink(tree, fname);
+
+ talloc_free(tree);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/**
+ * test getting security descriptor after reauth
+ */
+bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ bool ret = true;
+ union smb_fileinfo qfinfo;
+ struct cli_credentials *anon_creds = NULL;
+ uint32_t secinfo_flags = SECINFO_OWNER
+ | SECINFO_GROUP
+ | SECINFO_DACL
+ | SECINFO_PROTECTED_DACL
+ | SECINFO_UNPROTECTED_DACL;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_reauth3_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /* re-authenticate as anonymous */
+
+ anon_creds = cli_credentials_init_anon(mem_ctx);
+ torture_assert(tctx, (anon_creds != NULL), "talloc error");
+
+ status = smb2_session_setup_spnego(tree->session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /* re-authenticate as original user again */
+
+ status = smb2_session_setup_spnego(tree->session,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ smb2_util_unlink(tree, fname);
+
+ talloc_free(tree);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/**
+ * test setting security descriptor after reauth.
+ */
+bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ bool ret = true;
+ union smb_fileinfo qfinfo;
+ union smb_setfileinfo sfinfo;
+ struct cli_credentials *anon_creds = NULL;
+ uint32_t secinfo_flags = SECINFO_OWNER
+ | SECINFO_GROUP
+ | SECINFO_DACL
+ | SECINFO_PROTECTED_DACL
+ | SECINFO_UNPROTECTED_DACL;
+ struct security_descriptor *sd1;
+ struct security_ace ace;
+ struct dom_sid *extra_sid;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_reauth4_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ sd1 = qfinfo.query_secdesc.out.sd;
+
+ /* re-authenticate as anonymous */
+
+ anon_creds = cli_credentials_init_anon(mem_ctx);
+ torture_assert(tctx, (anon_creds != NULL), "talloc error");
+
+ status = smb2_session_setup_spnego(tree->session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* give full access on the file to anonymous */
+
+ extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
+
+ ZERO_STRUCT(ace);
+ ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+ ace.flags = 0;
+ ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
+ ace.trustee = *extra_sid;
+
+ status = security_descriptor_dacl_add(sd1, &ace);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "security_descriptor_dacl_add failed");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
+ sfinfo.set_secdesc.in.file.handle = _h1;
+ sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
+ sfinfo.set_secdesc.in.sd = sd1;
+
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_setinfo_file failed");
+
+ /* re-authenticate as original user again */
+
+ status = smb2_session_setup_spnego(tree->session,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* re-get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ ret = true;
+
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ smb2_util_unlink(tree, fname);
+
+ talloc_free(tree);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/**
+ * test renaming after reauth.
+ * compare security descriptors before and after rename/reauth
+ */
+bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char dname[128];
+ char fname[256];
+ char fname2[256];
+ struct smb2_handle _dh1;
+ struct smb2_handle *dh1 = NULL;
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ bool ret = true;
+ bool ok;
+ union smb_fileinfo qfinfo;
+ union smb_setfileinfo sfinfo;
+ struct cli_credentials *anon_creds = NULL;
+ uint32_t secinfo_flags = SECINFO_OWNER
+ | SECINFO_GROUP
+ | SECINFO_DACL
+ | SECINFO_PROTECTED_DACL
+ | SECINFO_UNPROTECTED_DACL;
+ struct security_descriptor *f_sd1;
+ struct security_descriptor *d_sd1 = NULL;
+ struct security_ace ace;
+ struct dom_sid *extra_sid;
+
+ /* Add some random component to the file name. */
+ snprintf(dname, sizeof(dname), "session_reauth5_%s.d",
+ generate_random_str(tctx, 8));
+ snprintf(fname, sizeof(fname), "%s\\file.dat", dname);
+
+ ok = smb2_util_setup_dir(tctx, tree, dname);
+ torture_assert(tctx, ok, "smb2_util_setup_dir not ok");
+
+ status = torture_smb2_testdir(tree, dname, &_dh1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir failed");
+ dh1 = &_dh1;
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ f_sd1 = qfinfo.query_secdesc.out.sd;
+
+ /* re-authenticate as anonymous */
+
+ anon_creds = cli_credentials_init_anon(mem_ctx);
+ torture_assert(tctx, (anon_creds != NULL), "talloc error");
+
+ status = smb2_session_setup_spnego(tree->session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to rename the file: fails */
+
+ snprintf(fname2, sizeof(fname2), "%s\\file2.dat", dname);
+
+ status = smb2_util_unlink(tree, fname2);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed");
+
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sfinfo.rename_information.in.file.handle = _h1;
+ sfinfo.rename_information.in.overwrite = true;
+ sfinfo.rename_information.in.new_name = fname2;
+
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_ACCESS_DENIED,
+ ret, done, "smb2_setinfo_file "
+ "returned unexpected status");
+
+ /* re-authenticate as original user again */
+
+ status = smb2_session_setup_spnego(tree->session,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* give full access on the file to anonymous */
+
+ extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
+
+ ZERO_STRUCT(ace);
+ ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+ ace.flags = 0;
+ ace.access_mask = SEC_RIGHTS_FILE_ALL;
+ ace.trustee = *extra_sid;
+
+ status = security_descriptor_dacl_add(f_sd1, &ace);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "security_descriptor_dacl_add failed");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
+ sfinfo.set_secdesc.in.file.handle = _h1;
+ sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
+ sfinfo.set_secdesc.in.sd = f_sd1;
+
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_setinfo_file failed");
+
+ /* re-get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /* re-authenticate as anonymous - again */
+
+ anon_creds = cli_credentials_init_anon(mem_ctx);
+ torture_assert(tctx, (anon_creds != NULL), "talloc error");
+
+ status = smb2_session_setup_spnego(tree->session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* try to rename the file: fails */
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sfinfo.rename_information.in.file.handle = _h1;
+ sfinfo.rename_information.in.overwrite = true;
+ sfinfo.rename_information.in.new_name = fname2;
+
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_ACCESS_DENIED,
+ ret, done, "smb2_setinfo_file "
+ "returned unexpected status");
+
+ /* give full access on the parent dir to anonymous */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _dh1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ d_sd1 = qfinfo.query_secdesc.out.sd;
+
+ ZERO_STRUCT(ace);
+ ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+ ace.flags = 0;
+ ace.access_mask = SEC_RIGHTS_FILE_ALL;
+ ace.trustee = *extra_sid;
+
+ status = security_descriptor_dacl_add(d_sd1, &ace);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "security_descriptor_dacl_add failed");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
+ sfinfo.set_secdesc.in.file.handle = _dh1;
+ sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
+ sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
+ sfinfo.set_secdesc.in.sd = d_sd1;
+
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_setinfo_file failed");
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _dh1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ status = smb2_util_close(tree, _dh1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+ dh1 = NULL;
+
+ /* try to rename the file: still fails */
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sfinfo.rename_information.in.file.handle = _h1;
+ sfinfo.rename_information.in.overwrite = true;
+ sfinfo.rename_information.in.new_name = fname2;
+
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_ACCESS_DENIED,
+ ret, done, "smb2_setinfo_file "
+ "returned unexpected status");
+
+ /* re-authenticate as original user - again */
+
+ status = smb2_session_setup_spnego(tree->session,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* rename the file - for verification that it works */
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sfinfo.rename_information.in.file.handle = _h1;
+ sfinfo.rename_information.in.overwrite = true;
+ sfinfo.rename_information.in.new_name = fname2;
+
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_setinfo_file failed");
+
+ /* closs the file, check it is gone and reopen under the new name */
+
+ status = smb2_util_close(tree, _h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+ ZERO_STRUCT(io1);
+
+ smb2_generic_create_share(&io1,
+ NULL /* lease */, false /* dir */,
+ fname,
+ NTCREATEX_DISP_OPEN,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"),
+ 0 /* leasekey */, 0 /* leasestate */);
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "smb2_create "
+ "returned unexpected status");
+
+ ZERO_STRUCT(io1);
+
+ smb2_generic_create_share(&io1,
+ NULL /* lease */, false /* dir */,
+ fname2,
+ NTCREATEX_DISP_OPEN,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"),
+ 0 /* leasekey */, 0 /* leasestate */);
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* try to access the file via the old handle */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ qfinfo.query_secdesc.in.file.handle = _h1;
+ qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
+
+ status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+done:
+ if (dh1 != NULL) {
+ smb2_util_close(tree, *dh1);
+ }
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ smb2_deltree(tree, dname);
+
+ talloc_free(tree);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/**
+ * do reauth with wrong credentials,
+ * hence triggering the error path in reauth.
+ * The invalid reauth deletes the session.
+ */
+bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ bool ret = true;
+ char *corrupted_password;
+ struct cli_credentials *broken_creds;
+ bool ok;
+ bool encrypted;
+ NTSTATUS expected;
+ enum credentials_use_kerberos krb_state;
+
+ krb_state = cli_credentials_get_kerberos_state(
+ samba_cmdline_get_creds());
+ if (krb_state == CRED_USE_KERBEROS_REQUIRED) {
+ torture_skip(tctx,
+ "Can't test failing session setup with kerberos.");
+ }
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+ io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /*
+ * reauthentication with invalid credentials:
+ */
+
+ broken_creds = cli_credentials_shallow_copy(mem_ctx,
+ samba_cmdline_get_creds());
+ torture_assert(tctx, (broken_creds != NULL), "talloc error");
+
+ corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
+ cli_credentials_get_password(broken_creds),
+ "corrupt");
+ torture_assert(tctx, (corrupted_password != NULL), "talloc error");
+
+ ok = cli_credentials_set_password(broken_creds, corrupted_password,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_password not ok");
+
+ status = smb2_session_setup_spnego(tree->session,
+ broken_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_LOGON_FAILURE, ret, done,
+ "smb2_session_setup_spnego "
+ "returned unexpected status");
+
+ torture_comment(tctx, "did failed reauth\n");
+ /*
+ * now verify that the invalid session reauth has closed our session
+ */
+
+ if (encrypted) {
+ expected = NT_STATUS_CONNECTION_DISCONNECTED;
+ } else {
+ expected = NT_STATUS_USER_SESSION_DELETED;
+ }
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ torture_assert_ntstatus_equal_goto(tctx, status, expected,
+ ret, done, "smb2_create "
+ "returned unexpected status");
+
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ smb2_util_unlink(tree, fname);
+
+ talloc_free(tree);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+
+static bool test_session_expire1i(struct torture_context *tctx,
+ bool force_signing,
+ bool force_encryption)
+{
+ NTSTATUS status;
+ bool ret = false;
+ struct smbcli_options options;
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ struct smb2_tree *tree = NULL;
+ enum credentials_use_kerberos use_kerberos;
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ union smb_fileinfo qfinfo;
+ size_t i;
+
+ use_kerberos = cli_credentials_get_kerberos_state(credentials);
+ if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
+ torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
+ torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
+ }
+
+ torture_assert_int_equal(tctx, use_kerberos, CRED_USE_KERBEROS_REQUIRED,
+ "please use -k yes");
+
+ cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+
+ lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
+
+ lpcfg_smbcli_options(tctx->lp_ctx, &options);
+ if (force_signing) {
+ options.signing = SMB_SIGNING_REQUIRED;
+ }
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect failed");
+
+ if (force_encryption) {
+ status = smb2cli_session_encryption_on(tree->session->smbXcli);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2cli_session_encryption_on failed");
+ }
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+ io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+
+ status = smb2_create(tree, tctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
+ qfinfo.access_information.in.file.handle = _h1;
+
+ for (i=0; i < 2; i++) {
+ torture_comment(tctx, "query info => OK\n");
+
+ ZERO_STRUCT(qfinfo.access_information.out);
+ status = smb2_getinfo_file(tree, tctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ torture_comment(tctx, "sleep 10 seconds\n");
+ smb_msleep(10*1000);
+
+ torture_comment(tctx, "query info => EXPIRED\n");
+ ZERO_STRUCT(qfinfo.access_information.out);
+ status = smb2_getinfo_file(tree, tctx, &qfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_getinfo_file "
+ "returned unexpected status");
+
+ /*
+ * the krb5 library may not handle expired creds
+ * well, lets start with an empty ccache.
+ */
+ cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+
+ if (!force_encryption) {
+ smb2cli_session_require_signed_response(
+ tree->session->smbXcli, true);
+ }
+
+ torture_comment(tctx, "reauth => OK\n");
+ status = smb2_session_setup_spnego(tree->session,
+ credentials,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ smb2cli_session_require_signed_response(
+ tree->session->smbXcli, false);
+ }
+
+ ZERO_STRUCT(qfinfo.access_information.out);
+ status = smb2_getinfo_file(tree, tctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ ret = true;
+done:
+ cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ talloc_free(tree);
+ lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
+ return ret;
+}
+
+static bool test_session_expire1n(struct torture_context *tctx)
+{
+ return test_session_expire1i(tctx,
+ false, /* force_signing */
+ false); /* force_encryption */
+}
+
+static bool test_session_expire1s(struct torture_context *tctx)
+{
+ return test_session_expire1i(tctx,
+ true, /* force_signing */
+ false); /* force_encryption */
+}
+
+static bool test_session_expire1e(struct torture_context *tctx)
+{
+ return test_session_expire1i(tctx,
+ true, /* force_signing */
+ true); /* force_encryption */
+}
+
+static bool test_session_expire2i(struct torture_context *tctx,
+ bool force_encryption)
+{
+ NTSTATUS status;
+ bool ret = false;
+ struct smbcli_options options;
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ struct smb2_tree *tree = NULL;
+ const char *unc = NULL;
+ struct smb2_tree *tree2 = NULL;
+ struct tevent_req *subreq = NULL;
+ uint32_t timeout_msec;
+ enum credentials_use_kerberos use_kerberos;
+ uint32_t caps;
+ char fname[256];
+ struct smb2_handle dh;
+ struct smb2_handle dh2;
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ union smb_fileinfo qfinfo;
+ union smb_setfileinfo sfinfo;
+ struct smb2_flush flsh;
+ struct smb2_read rd;
+ const uint8_t wd = 0;
+ struct smb2_lock lck;
+ struct smb2_lock_element el;
+ struct smb2_ioctl ctl;
+ struct smb2_break oack;
+ struct smb2_lease_break_ack lack;
+ struct smb2_find fnd;
+ union smb_search_data *d = NULL;
+ unsigned int count;
+ struct smb2_request *req = NULL;
+ struct smb2_notify ntf1;
+ struct smb2_notify ntf2;
+
+ use_kerberos = cli_credentials_get_kerberos_state(credentials);
+ if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
+ torture_warning(tctx, "smb2.session.expire2 requires -k yes!");
+ torture_skip(tctx, "smb2.session.expire2 requires -k yes!");
+ }
+
+ torture_assert_int_equal(tctx, use_kerberos, CRED_USE_KERBEROS_REQUIRED,
+ "please use -k yes");
+
+ cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+
+ lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
+
+ lpcfg_smbcli_options(tctx->lp_ctx, &options);
+ options.signing = SMB_SIGNING_REQUIRED;
+
+ unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
+ torture_assert(tctx, unc != NULL, "talloc_asprintf");
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect failed");
+
+ if (force_encryption) {
+ status = smb2cli_session_encryption_on(tree->session->smbXcli);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2cli_session_encryption_on failed");
+ }
+
+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_expire2_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ status = smb2_util_roothandle(tree, &dh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_roothandle failed");
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+ io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+
+ status = smb2_create(tree, tctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
+ qfinfo.access_information.in.file.handle = _h1;
+
+ torture_comment(tctx, "query info => OK\n");
+
+ ZERO_STRUCT(qfinfo.access_information.out);
+ status = smb2_getinfo_file(tree, tctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ torture_comment(tctx, "lock => OK\n");
+ ZERO_STRUCT(lck);
+ lck.in.locks = &el;
+ lck.in.lock_count = 0x0001;
+ lck.in.lock_sequence = 0x00000000;
+ lck.in.file.handle = *h1;
+ ZERO_STRUCT(el);
+ el.flags = SMB2_LOCK_FLAG_EXCLUSIVE |
+ SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
+ el.offset = 0x0000000000000000;
+ el.length = 0x0000000000000001;
+ status = smb2_lock(tree, &lck);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_lock lock failed");
+
+ torture_comment(tctx, "1st notify => PENDING\n");
+ ZERO_STRUCT(ntf1);
+ ntf1.in.file.handle = dh;
+ ntf1.in.recursive = 0x0000;
+ ntf1.in.buffer_size = 128;
+ ntf1.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+ ntf1.in.unknown = 0x00000000;
+ req = smb2_notify_send(tree, &ntf1);
+
+ while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
+ if (tevent_loop_once(tctx->ev) != 0) {
+ break;
+ }
+ }
+
+ torture_assert_goto(tctx, req->state <= SMB2_REQUEST_RECV, ret, done,
+ "smb2_notify finished");
+
+ torture_comment(tctx, "sleep 10 seconds\n");
+ smb_msleep(10*1000);
+
+ torture_comment(tctx, "query info => EXPIRED\n");
+ ZERO_STRUCT(qfinfo.access_information.out);
+ status = smb2_getinfo_file(tree, tctx, &qfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_getinfo_file "
+ "returned unexpected status");
+
+
+ torture_comment(tctx, "set info => EXPIRED\n");
+ ZERO_STRUCT(sfinfo);
+ sfinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.end_of_file_info.in.file.handle = *h1;
+ sfinfo.end_of_file_info.in.size = 1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_setinfo_file "
+ "returned unexpected status");
+
+ torture_comment(tctx, "flush => EXPIRED\n");
+ ZERO_STRUCT(flsh);
+ flsh.in.file.handle = *h1;
+ status = smb2_flush(tree, &flsh);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_flush "
+ "returned unexpected status");
+
+ torture_comment(tctx, "read => EXPIRED\n");
+ ZERO_STRUCT(rd);
+ rd.in.file.handle = *h1;
+ rd.in.length = 5;
+ rd.in.offset = 0;
+ status = smb2_read(tree, tctx, &rd);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_read "
+ "returned unexpected status");
+
+ torture_comment(tctx, "write => EXPIRED\n");
+ status = smb2_util_write(tree, *h1, &wd, 0, 1);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_util_write "
+ "returned unexpected status");
+
+ torture_comment(tctx, "ioctl => EXPIRED\n");
+ ZERO_STRUCT(ctl);
+ ctl.in.file.handle = *h1;
+ ctl.in.function = FSCTL_SRV_ENUM_SNAPS;
+ ctl.in.max_output_response = 16;
+ ctl.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
+ status = smb2_ioctl(tree, tctx, &ctl);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_ioctl "
+ "returned unexpected status");
+
+ torture_comment(tctx, "oplock ack => EXPIRED\n");
+ ZERO_STRUCT(oack);
+ oack.in.file.handle = *h1;
+ status = smb2_break(tree, &oack);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_break "
+ "returned unexpected status");
+
+ if (caps & SMB2_CAP_LEASING) {
+ torture_comment(tctx, "lease ack => EXPIRED\n");
+ ZERO_STRUCT(lack);
+ lack.in.lease.lease_version = 1;
+ lack.in.lease.lease_key.data[0] = 1;
+ lack.in.lease.lease_key.data[1] = 2;
+ status = smb2_lease_break_ack(tree, &lack);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_break "
+ "returned unexpected status");
+ }
+
+ torture_comment(tctx, "query directory => EXPIRED\n");
+ ZERO_STRUCT(fnd);
+ fnd.in.file.handle = dh;
+ fnd.in.pattern = "*";
+ fnd.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
+ fnd.in.max_response_size= 0x100;
+ fnd.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
+ status = smb2_find_level(tree, tree, &fnd, &count, &d);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_find_level "
+ "returned unexpected status");
+
+ torture_comment(tctx, "1st notify => CANCEL\n");
+ smb2_cancel(req);
+
+ torture_comment(tctx, "2nd notify => EXPIRED\n");
+ ZERO_STRUCT(ntf2);
+ ntf2.in.file.handle = dh;
+ ntf2.in.recursive = 0x0000;
+ ntf2.in.buffer_size = 128;
+ ntf2.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+ ntf2.in.unknown = 0x00000000;
+ status = smb2_notify(tree, tctx, &ntf2);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_notify "
+ "returned unexpected status");
+
+ torture_assert_goto(tctx, req->state > SMB2_REQUEST_RECV, ret, done,
+ "smb2_notify (1st) not finished");
+
+ status = smb2_notify_recv(req, tctx, &ntf1);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_CANCELLED,
+ ret, done, "smb2_notify cancelled"
+ "returned unexpected status");
+
+ torture_comment(tctx, "tcon => EXPIRED\n");
+ tree2 = smb2_tree_init(tree->session, tctx, false);
+ torture_assert(tctx, tree2 != NULL, "smb2_tree_init");
+ timeout_msec = tree->session->transport->options.request_timeout * 1000;
+ subreq = smb2cli_tcon_send(tree2, tctx->ev,
+ tree2->session->transport->conn,
+ timeout_msec,
+ tree2->session->smbXcli,
+ tree2->smbXcli,
+ 0, /* flags */
+ unc);
+ torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
+ torture_assert(tctx,
+ tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
+ "tevent_req_poll_ntstatus");
+ status = smb2cli_tcon_recv(subreq);
+ TALLOC_FREE(subreq);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2cli_tcon"
+ "returned unexpected status");
+
+ torture_comment(tctx, "create => EXPIRED\n");
+ status = smb2_util_roothandle(tree, &dh2);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_util_roothandle"
+ "returned unexpected status");
+
+ torture_comment(tctx, "tdis => EXPIRED\n");
+ status = smb2_tdis(tree);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2cli_tdis"
+ "returned unexpected status");
+
+ /*
+ * (Un)Lock, Close and Logoff are still possible
+ */
+
+ torture_comment(tctx, "1st unlock => OK\n");
+ el.flags = SMB2_LOCK_FLAG_UNLOCK;
+ status = smb2_lock(tree, &lck);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_lock unlock failed");
+
+ torture_comment(tctx, "2nd unlock => RANGE_NOT_LOCKED\n");
+ status = smb2_lock(tree, &lck);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_RANGE_NOT_LOCKED,
+ ret, done, "smb2_lock 2nd unlock"
+ "returned unexpected status");
+
+ torture_comment(tctx, "lock => EXPIRED\n");
+ el.flags = SMB2_LOCK_FLAG_EXCLUSIVE |
+ SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
+ status = smb2_lock(tree, &lck);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_util_roothandle"
+ "returned unexpected status");
+
+ torture_comment(tctx, "close => OK\n");
+ status = smb2_util_close(tree, *h1);
+ h1 = NULL;
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_close failed");
+
+ torture_comment(tctx, "echo without session => OK\n");
+ status = smb2_keepalive(tree->session->transport);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_keepalive without session failed");
+
+ torture_comment(tctx, "echo with session => OK\n");
+ req = smb2_keepalive_send(tree->session->transport, tree->session);
+ status = smb2_keepalive_recv(req);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_keepalive with session failed");
+
+ torture_comment(tctx, "logoff => OK\n");
+ status = smb2_logoff(tree->session);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_logoff failed");
+
+ ret = true;
+done:
+ cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ talloc_free(tree);
+ lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
+ return ret;
+}
+
+static bool test_session_expire2s(struct torture_context *tctx)
+{
+ return test_session_expire2i(tctx,
+ false); /* force_encryption */
+}
+
+static bool test_session_expire2e(struct torture_context *tctx)
+{
+ return test_session_expire2i(tctx,
+ true); /* force_encryption */
+}
+
+static bool test_session_expire_disconnect(struct torture_context *tctx)
+{
+ NTSTATUS status;
+ bool ret = false;
+ struct smbcli_options options;
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ struct smb2_tree *tree = NULL;
+ enum credentials_use_kerberos use_kerberos;
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ union smb_fileinfo qfinfo;
+ bool connected;
+
+ use_kerberos = cli_credentials_get_kerberos_state(credentials);
+ if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
+ torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
+ torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
+ }
+
+ cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+
+ lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
+ lpcfg_smbcli_options(tctx->lp_ctx, &options);
+ options.signing = SMB_SIGNING_REQUIRED;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect failed");
+
+ smbXcli_session_set_disconnect_expired(tree->session->smbXcli);
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+ io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+
+ status = smb2_create(tree, tctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* get the security descriptor */
+
+ ZERO_STRUCT(qfinfo);
+
+ qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
+ qfinfo.access_information.in.file.handle = _h1;
+
+ torture_comment(tctx, "query info => OK\n");
+
+ ZERO_STRUCT(qfinfo.access_information.out);
+ status = smb2_getinfo_file(tree, tctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ torture_comment(tctx, "sleep 10 seconds\n");
+ smb_msleep(10*1000);
+
+ torture_comment(tctx, "query info => EXPIRED\n");
+ ZERO_STRUCT(qfinfo.access_information.out);
+ status = smb2_getinfo_file(tree, tctx, &qfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ NT_STATUS_NETWORK_SESSION_EXPIRED,
+ ret, done, "smb2_getinfo_file "
+ "returned unexpected status");
+
+ connected = smbXcli_conn_is_connected(tree->session->transport->conn);
+ torture_assert_goto(tctx, !connected, ret, done, "connected\n");
+
+ ret = true;
+done:
+ cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+
+ talloc_free(tree);
+ lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
+ return ret;
+}
+
+bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ union smb_fileinfo qfinfo;
+ bool ret = false;
+ struct smb2_tree *tree2 = NULL;
+ struct smb2_transport *transport1 = tree1->session->transport;
+ struct smbcli_options options2;
+ struct smb2_transport *transport2 = NULL;
+ struct smb2_session *session1_1 = tree1->session;
+ struct smb2_session *session1_2 = NULL;
+ struct smb2_session *session2_1 = NULL;
+ struct smb2_session *session2_2 = NULL;
+ uint32_t caps;
+
+ caps = smb2cli_conn_server_capabilities(transport1->conn);
+ if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
+ torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
+ }
+
+ /*
+ * We always want signing for this test!
+ */
+ smb2cli_tcon_should_sign(tree1->smbXcli, true);
+ options2 = transport1->options;
+ options2.signing = SMB_SIGNING_REQUIRED;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree1, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree1, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree2,
+ tctx->ev,
+ &options2,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect failed");
+ session2_2 = tree2->session;
+ transport2 = tree2->session->transport;
+
+ /*
+ * Now bind the 2nd transport connection to the 1st session
+ */
+ session1_2 = smb2_session_channel(transport2,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2,
+ session1_1);
+ torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session1_2,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* use the 1st connection, 1st session */
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ tree1->session = session1_1;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /* use the 2nd connection, 1st session */
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ tree1->session = session1_2;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ tree1->session = session1_1;
+ status = smb2_util_close(tree1, *h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+ h1 = NULL;
+
+ /*
+ * Now bind the 1st transport connection to the 2nd session
+ */
+ session2_1 = smb2_session_channel(transport1,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree1,
+ session2_2);
+ torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session2_1,
+ samba_cmdline_get_creds(),
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ tree2->session = session2_1;
+ status = smb2_util_unlink(tree2, fname);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed");
+ ret = true;
+done:
+ talloc_free(tree2);
+ tree1->session = session1_1;
+
+ if (h1 != NULL) {
+ smb2_util_close(tree1, *h1);
+ }
+
+ smb2_util_unlink(tree1, fname);
+
+ talloc_free(tree1);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+static bool test_session_bind2(struct torture_context *tctx, struct smb2_tree *tree1)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname1[256];
+ char fname2[256];
+ struct smb2_handle _h1f1;
+ struct smb2_handle *h1f1 = NULL;
+ struct smb2_handle _h1f2;
+ struct smb2_handle *h1f2 = NULL;
+ struct smb2_handle _h2f2;
+ struct smb2_handle *h2f2 = NULL;
+ struct smb2_create io1f1;
+ struct smb2_create io1f2;
+ struct smb2_create io2f1;
+ struct smb2_create io2f2;
+ union smb_fileinfo qfinfo;
+ bool ret = false;
+ struct smb2_transport *transport1 = tree1->session->transport;
+ struct smbcli_options options2;
+ struct smb2_tree *tree2 = NULL;
+ struct smb2_transport *transport2 = NULL;
+ struct smbcli_options options3;
+ struct smb2_tree *tree3 = NULL;
+ struct smb2_transport *transport3 = NULL;
+ struct smb2_session *session1_1 = tree1->session;
+ struct smb2_session *session1_2 = NULL;
+ struct smb2_session *session1_3 = NULL;
+ struct smb2_session *session2_1 = NULL;
+ struct smb2_session *session2_2 = NULL;
+ struct smb2_session *session2_3 = NULL;
+ uint32_t caps;
+
+ caps = smb2cli_conn_server_capabilities(transport1->conn);
+ if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
+ torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
+ }
+
+ /*
+ * We always want signing for this test!
+ */
+ smb2cli_tcon_should_sign(tree1->smbXcli, true);
+ options2 = transport1->options;
+ options2.signing = SMB_SIGNING_REQUIRED;
+
+ /* Add some random component to the file name. */
+ snprintf(fname1, sizeof(fname1), "session_bind2_1_%s.dat",
+ generate_random_str(tctx, 8));
+ snprintf(fname2, sizeof(fname2), "session_bind2_2_%s.dat",
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree1, fname1);
+ smb2_util_unlink(tree1, fname2);
+
+ smb2_oplock_create_share(&io1f1, fname1,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level(""));
+ smb2_oplock_create_share(&io1f2, fname2,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level(""));
+
+ status = smb2_create(tree1, mem_ctx, &io1f1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1f1 = io1f1.out.file.handle;
+ h1f1 = &_h1f1;
+ CHECK_CREATED(tctx, &io1f1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1f1.out.oplock_level,
+ smb2_util_oplock_level(""),
+ "oplock_level incorrect");
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree2,
+ tctx->ev,
+ &options2,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect failed");
+ session2_2 = tree2->session;
+ transport2 = tree2->session->transport;
+ smb2cli_tcon_should_sign(tree2->smbXcli, true);
+
+ smb2_oplock_create_share(&io2f1, fname1,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level(""));
+ smb2_oplock_create_share(&io2f2, fname2,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level(""));
+
+ status = smb2_create(tree2, mem_ctx, &io2f2);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h2f2 = io2f2.out.file.handle;
+ h2f2 = &_h2f2;
+ CHECK_CREATED(tctx, &io2f2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io2f2.out.oplock_level,
+ smb2_util_oplock_level(""),
+ "oplock_level incorrect");
+
+ options3 = transport1->options;
+ options3.signing = SMB_SIGNING_REQUIRED;
+ options3.only_negprot = true;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree3,
+ tctx->ev,
+ &options3,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect failed");
+ transport3 = tree3->session->transport;
+
+ /*
+ * Create a fake session for the 2nd transport connection to the 1st session
+ */
+ session1_2 = smb2_session_channel(transport2,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree1,
+ session1_1);
+ torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
+
+ /*
+ * Now bind the 3rd transport connection to the 1st session
+ */
+ session1_3 = smb2_session_channel(transport3,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree1,
+ session1_1);
+ torture_assert(tctx, session1_3 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session1_3,
+ credentials,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /*
+ * Create a fake session for the 1st transport connection to the 2nd session
+ */
+ session2_1 = smb2_session_channel(transport1,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2,
+ session2_2);
+ torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
+
+ /*
+ * Now bind the 3rd transport connection to the 2nd session
+ */
+ session2_3 = smb2_session_channel(transport3,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2,
+ session2_2);
+ torture_assert(tctx, session2_3 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session2_3,
+ credentials,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1f1;
+ tree1->session = session1_1;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+ tree1->session = session1_2;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_getinfo_file failed");
+ tree1->session = session1_3;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h2f2;
+ tree2->session = session2_1;
+ status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_getinfo_file failed");
+ tree2->session = session2_2;
+ status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+ tree2->session = session2_3;
+ status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ tree1->session = session1_1;
+ status = smb2_create(tree1, mem_ctx, &io1f2);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
+ "smb2_create failed");
+ tree1->session = session1_2;
+ status = smb2_create(tree1, mem_ctx, &io1f2);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_create failed");
+ tree1->session = session1_3;
+ status = smb2_create(tree1, mem_ctx, &io1f2);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
+ "smb2_create failed");
+
+ tree2->session = session2_1;
+ status = smb2_create(tree2, mem_ctx, &io2f1);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_create failed");
+ tree2->session = session2_2;
+ status = smb2_create(tree2, mem_ctx, &io2f1);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
+ "smb2_create failed");
+ tree2->session = session2_3;
+ status = smb2_create(tree2, mem_ctx, &io2f1);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
+ "smb2_create failed");
+
+ smbXcli_conn_disconnect(transport3->conn, NT_STATUS_LOCAL_DISCONNECT);
+ smb_msleep(500);
+
+ tree1->session = session1_1;
+ status = smb2_create(tree1, mem_ctx, &io1f2);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
+ "smb2_create failed");
+ tree1->session = session1_2;
+ status = smb2_create(tree1, mem_ctx, &io1f2);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_create failed");
+
+ tree2->session = session2_1;
+ status = smb2_create(tree2, mem_ctx, &io2f1);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_create failed");
+ tree2->session = session2_2;
+ status = smb2_create(tree2, mem_ctx, &io2f1);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
+ "smb2_create failed");
+
+ smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
+ smb_msleep(500);
+ h2f2 = NULL;
+
+ tree1->session = session1_1;
+ status = smb2_create(tree1, mem_ctx, &io1f2);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1f2 = io1f2.out.file.handle;
+ h1f2 = &_h1f2;
+ CHECK_CREATED(tctx, &io1f2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1f2.out.oplock_level,
+ smb2_util_oplock_level(""),
+ "oplock_level incorrect");
+
+ tree1->session = session1_1;
+ status = smb2_util_close(tree1, *h1f1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+ h1f1 = NULL;
+
+ ret = true;
+done:
+
+ smbXcli_conn_disconnect(transport3->conn, NT_STATUS_LOCAL_DISCONNECT);
+ smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
+
+ tree1->session = session1_1;
+ tree2->session = session2_2;
+
+ if (h1f1 != NULL) {
+ smb2_util_close(tree1, *h1f1);
+ }
+ if (h1f2 != NULL) {
+ smb2_util_close(tree1, *h1f2);
+ }
+ if (h2f2 != NULL) {
+ smb2_util_close(tree2, *h2f2);
+ }
+
+ smb2_util_unlink(tree1, fname1);
+ smb2_util_unlink(tree1, fname2);
+
+ talloc_free(tree1);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+static bool test_session_bind_auth_mismatch(struct torture_context *tctx,
+ struct smb2_tree *tree1,
+ const char *testname,
+ struct cli_credentials *creds1,
+ struct cli_credentials *creds2,
+ bool creds2_require_ok)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ union smb_fileinfo qfinfo;
+ bool ret = false;
+ struct smb2_tree *tree2 = NULL;
+ struct smb2_transport *transport1 = tree1->session->transport;
+ struct smbcli_options options2;
+ struct smb2_transport *transport2 = NULL;
+ struct smb2_session *session1_1 = tree1->session;
+ struct smb2_session *session1_2 = NULL;
+ struct smb2_session *session2_1 = NULL;
+ struct smb2_session *session2_2 = NULL;
+ struct smb2_session *session3_1 = NULL;
+ uint32_t caps;
+ bool encrypted;
+ bool creds2_got_ok = false;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree1->smbXcli);
+
+ caps = smb2cli_conn_server_capabilities(transport1->conn);
+ if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
+ torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
+ }
+
+ /*
+ * We always want signing for this test!
+ */
+ smb2cli_tcon_should_sign(tree1->smbXcli, true);
+ options2 = transport1->options;
+ options2.signing = SMB_SIGNING_REQUIRED;
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "%s_%s.dat", testname,
+ generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree1, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ status = smb2_create(tree1, mem_ctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ creds1,
+ &tree2,
+ tctx->ev,
+ &options2,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect failed");
+ session2_2 = tree2->session;
+ transport2 = tree2->session->transport;
+
+ /*
+ * Now bind the 2nd transport connection to the 1st session
+ */
+ session1_2 = smb2_session_channel(transport2,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2,
+ session1_1);
+ torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session1_2,
+ creds1,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+
+ /* use the 1st connection, 1st session */
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ tree1->session = session1_1;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /* use the 2nd connection, 1st session */
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = _h1;
+ tree1->session = session1_2;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ tree1->session = session1_1;
+ status = smb2_util_close(tree1, *h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+ h1 = NULL;
+
+ /*
+ * Create a 3rd session in order to check if the invalid (creds2)
+ * are mapped to guest.
+ */
+ session3_1 = smb2_session_init(transport1,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tctx);
+ torture_assert(tctx, session3_1 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session3_1,
+ creds2,
+ 0 /* previous_session_id */);
+ if (creds2_require_ok) {
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego worked");
+ creds2_got_ok = true;
+ } else if (NT_STATUS_IS_OK(status)) {
+ bool authentiated = smbXcli_session_is_authenticated(session3_1->smbXcli);
+ torture_assert(tctx, !authentiated, "Invalid credentials allowed!");
+ creds2_got_ok = true;
+ } else {
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_LOGON_FAILURE, ret, done,
+ "smb2_session_setup_spnego worked");
+ }
+
+ /*
+ * Now bind the 1st transport connection to the 2nd session
+ */
+ session2_1 = smb2_session_channel(transport1,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree1,
+ session2_2);
+ torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
+
+ tree2->session = session2_1;
+ status = smb2_util_unlink(tree2, fname);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_util_unlink worked on invalid channel");
+
+ status = smb2_session_setup_spnego(session2_1,
+ creds2,
+ 0 /* previous_session_id */);
+ if (creds2_got_ok) {
+ /*
+ * attaching with a different user (guest or anonymous) results
+ * in ACCESS_DENIED.
+ */
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED, ret, done,
+ "smb2_session_setup_spnego worked");
+ } else {
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_LOGON_FAILURE, ret, done,
+ "smb2_session_setup_spnego worked");
+ }
+
+ tree2->session = session2_1;
+ status = smb2_util_unlink(tree2, fname);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_util_unlink worked on invalid channel");
+
+ tree2->session = session2_2;
+ status = smb2_util_unlink(tree2, fname);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed");
+ status = smb2_util_unlink(tree2, fname);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "smb2_util_unlink worked");
+ if (creds2_got_ok) {
+ /*
+ * We got ACCESS_DENIED on the session bind
+ * with a different user, now check that
+ * the correct user can actually bind on
+ * the same connection.
+ */
+ TALLOC_FREE(session2_1);
+ session2_1 = smb2_session_channel(transport1,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree1,
+ session2_2);
+ torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session2_1,
+ creds1,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_session_setup_spnego failed");
+ tree2->session = session2_1;
+ status = smb2_util_unlink(tree2, fname);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "smb2_util_unlink worked");
+ tree2->session = session2_2;
+ }
+
+ tree1->session = session1_1;
+ status = smb2_util_unlink(tree1, fname);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "smb2_util_unlink worked");
+
+ tree1->session = session1_2;
+ status = smb2_util_unlink(tree1, fname);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "smb2_util_unlink worked");
+
+ if (creds2_got_ok) {
+ /*
+ * With valid credentials, there's no point to test a failing
+ * reauth.
+ */
+ ret = true;
+ goto done;
+ }
+
+ /*
+ * Do a failing reauth the 2nd channel
+ */
+ status = smb2_session_setup_spnego(session1_2,
+ creds2,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_LOGON_FAILURE, ret, done,
+ "smb2_session_setup_spnego worked");
+
+ tree1->session = session1_1;
+ status = smb2_util_unlink(tree1, fname);
+ if (encrypted) {
+ torture_assert_goto(tctx, !smbXcli_conn_is_connected(transport1->conn), ret, done,
+ "smb2_util_unlink worked");
+ } else {
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_util_unlink worked");
+ }
+
+ tree1->session = session1_2;
+ status = smb2_util_unlink(tree1, fname);
+ if (encrypted) {
+ torture_assert_goto(tctx, !smbXcli_conn_is_connected(transport2->conn), ret, done,
+ "smb2_util_unlink worked");
+ } else {
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
+ "smb2_util_unlink worked");
+ }
+
+ status = smb2_util_unlink(tree2, fname);
+ if (encrypted) {
+ torture_assert_goto(tctx, !smbXcli_conn_is_connected(transport1->conn), ret, done,
+ "smb2_util_unlink worked");
+ torture_assert_goto(tctx, !smbXcli_conn_is_connected(transport2->conn), ret, done,
+ "smb2_util_unlink worked");
+ } else {
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "smb2_util_unlink worked");
+ }
+
+ ret = true;
+done:
+ talloc_free(tree2);
+ tree1->session = session1_1;
+
+ if (h1 != NULL) {
+ smb2_util_close(tree1, *h1);
+ }
+
+ smb2_util_unlink(tree1, fname);
+
+ talloc_free(tree1);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+static bool test_session_bind_invalid_auth(struct torture_context *tctx, struct smb2_tree *tree1)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ struct cli_credentials *invalid_credentials = NULL;
+ bool ret = false;
+
+ invalid_credentials = cli_credentials_init(tctx);
+ torture_assert(tctx, (invalid_credentials != NULL), "talloc error");
+ cli_credentials_set_username(invalid_credentials, "__none__invalid__none__", CRED_SPECIFIED);
+ cli_credentials_set_domain(invalid_credentials, "__none__invalid__none__", CRED_SPECIFIED);
+ cli_credentials_set_password(invalid_credentials, "__none__invalid__none__", CRED_SPECIFIED);
+ cli_credentials_set_realm(invalid_credentials, NULL, CRED_SPECIFIED);
+ cli_credentials_set_workstation(invalid_credentials, "", CRED_UNINITIALISED);
+
+ ret = test_session_bind_auth_mismatch(tctx, tree1, __func__,
+ credentials,
+ invalid_credentials,
+ false);
+ return ret;
+}
+
+static bool test_session_bind_different_user(struct torture_context *tctx, struct smb2_tree *tree1)
+{
+ struct cli_credentials *credentials1 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials2 = torture_user2_credentials(tctx, tctx);
+ char *u1 = cli_credentials_get_unparsed_name(credentials1, tctx);
+ char *u2 = cli_credentials_get_unparsed_name(credentials2, tctx);
+ bool ret = false;
+ bool bval;
+
+ torture_assert(tctx, (credentials2 != NULL), "talloc error");
+ bval = cli_credentials_is_anonymous(credentials2);
+ if (bval) {
+ torture_skip(tctx, "valid user2 credentials are required");
+ }
+ bval = strequal(u1, u2);
+ if (bval) {
+ torture_skip(tctx, "different user2 credentials are required");
+ }
+
+ ret = test_session_bind_auth_mismatch(tctx, tree1, __func__,
+ credentials1,
+ credentials2,
+ true);
+ return ret;
+}
+
+static bool test_session_bind_negative_smbXtoX(struct torture_context *tctx,
+ const char *testname,
+ struct cli_credentials *credentials,
+ const struct smbcli_options *options1,
+ const struct smbcli_options *options2,
+ NTSTATUS bind_reject_status)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ NTSTATUS status;
+ bool ret = false;
+ struct smb2_tree *tree1 = NULL;
+ struct smb2_session *session1_1 = NULL;
+ char fname[256];
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ union smb_fileinfo qfinfo1;
+ struct smb2_tree *tree2_0 = NULL;
+ struct smb2_transport *transport2 = NULL;
+ struct smb2_session *session1_2 = NULL;
+ uint64_t session1_id = 0;
+ uint16_t session1_flags = 0;
+ NTSTATUS deleted_status = NT_STATUS_USER_SESSION_DELETED;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree1,
+ tctx->ev,
+ options1,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect options1 failed");
+ session1_1 = tree1->session;
+ session1_id = smb2cli_session_current_id(session1_1->smbXcli);
+ session1_flags = smb2cli_session_get_flags(session1_1->smbXcli);
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "%s_%s.dat",
+ testname, generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree1, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ status = smb2_create(tree1, tctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ &tree2_0,
+ tctx->ev,
+ options2,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect options2 failed");
+ transport2 = tree2_0->session->transport;
+
+ /*
+ * Now bind the 2nd transport connection to the 1st session
+ */
+ session1_2 = smb2_session_channel(transport2,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2_0,
+ session1_1);
+ torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session1_2,
+ credentials,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_equal_goto(tctx, status, bind_reject_status, ret, done,
+ "smb2_session_setup_spnego failed");
+ if (NT_STATUS_IS_OK(bind_reject_status)) {
+ ZERO_STRUCT(qfinfo1);
+ qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo1.generic.in.file.handle = _h1;
+ tree1->session = session1_2;
+ status = smb2_getinfo_file(tree1, tctx, &qfinfo1);
+ tree1->session = session1_1;
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+ }
+ TALLOC_FREE(session1_2);
+
+ /* Check the initial session is still alive */
+ ZERO_STRUCT(qfinfo1);
+ qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo1.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree1, tctx, &qfinfo1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ if (NT_STATUS_IS_OK(bind_reject_status)) {
+ deleted_status = NT_STATUS_ACCESS_DENIED;
+ bind_reject_status = NT_STATUS_ACCESS_DENIED;
+ }
+
+ /*
+ * I guess this is not part of MultipleChannel_Negative_SMB2002,
+ * but we should also check the status without
+ * SMB2_SESSION_FLAG_BINDING.
+ */
+ session1_2 = smb2_session_channel(transport2,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2_0,
+ session1_1);
+ torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
+ session1_2->needs_bind = false;
+
+ status = smb2_session_setup_spnego(session1_2,
+ credentials,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_equal_goto(tctx, status, deleted_status, ret, done,
+ "smb2_session_setup_spnego failed");
+ TALLOC_FREE(session1_2);
+
+ /*
+ * ... and we should also check the status without any existing
+ * session keys.
+ */
+ session1_2 = smb2_session_init(transport2,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2_0);
+ torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
+ talloc_steal(tree2_0->session, transport2);
+ smb2cli_session_set_id_and_flags(session1_2->smbXcli,
+ session1_id, session1_flags);
+
+ status = smb2_session_setup_spnego(session1_2,
+ credentials,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_equal_goto(tctx, status, deleted_status, ret, done,
+ "smb2_session_setup_spnego failed");
+ TALLOC_FREE(session1_2);
+
+ /* Check the initial session is still alive */
+ ZERO_STRUCT(qfinfo1);
+ qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo1.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree1, tctx, &qfinfo1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /*
+ * Now bind the 2nd transport connection to the 1st session (again)
+ */
+ session1_2 = smb2_session_channel(transport2,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tree2_0,
+ session1_1);
+ torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
+
+ status = smb2_session_setup_spnego(session1_2,
+ credentials,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_equal_goto(tctx, status, bind_reject_status, ret, done,
+ "smb2_session_setup_spnego failed");
+ TALLOC_FREE(session1_2);
+
+ /* Check the initial session is still alive */
+ ZERO_STRUCT(qfinfo1);
+ qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo1.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree1, tctx, &qfinfo1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ ret = true;
+done:
+ talloc_free(tree2_0);
+ if (h1 != NULL) {
+ smb2_util_close(tree1, *h1);
+ }
+ talloc_free(tree1);
+
+ return ret;
+}
+
+/*
+ * This is similar to the MultipleChannel_Negative_SMB2002 test
+ * from the Windows Protocol Test Suite.
+ *
+ * It demonstrates that the server needs to do lookup
+ * in the global session table in order to get the signing
+ * and error code of invalid session setups correct.
+ *
+ * See: https://bugzilla.samba.org/show_bug.cgi?id=14512
+ *
+ * Note you can ignore tree0...
+ */
+static bool test_session_bind_negative_smb202(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.02 if encryption is required");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_zero();
+ options1.max_protocol = PROTOCOL_SMB2_02;
+
+ options2 = options1;
+ options2.only_negprot = true;
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_NOT_ACCEPTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb210s(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.max_protocol = PROTOCOL_SMB2_10;
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_NOT_ACCEPTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb210d(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.max_protocol = PROTOCOL_SMB2_10;
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_NOT_ACCEPTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb2to3s(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB2_02;
+ options1.max_protocol = PROTOCOL_SMB2_10;
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_00;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_INVALID_PARAMETER);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb2to3d(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB2_02;
+ options1.max_protocol = PROTOCOL_SMB2_10;
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_00;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_INVALID_PARAMETER);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3to2s(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_00;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB2_02;
+ options2.max_protocol = PROTOCOL_SMB2_10;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_NOT_ACCEPTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3to2d(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_00;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB2_02;
+ options2.max_protocol = PROTOCOL_SMB2_10;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_NOT_ACCEPTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3to3s(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_02;
+ options1.max_protocol = PROTOCOL_SMB3_02;
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_11;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_INVALID_PARAMETER);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3to3d(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_02;
+ options1.max_protocol = PROTOCOL_SMB3_02;
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_11;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_INVALID_PARAMETER);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3encGtoCs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_INVALID_PARAMETER);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3encGtoCd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_INVALID_PARAMETER);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signCtoHs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_OK);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signCtoHd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_OK);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signHtoCs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_OK);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signHtoCd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_OK);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signHtoGs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signHtoGd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signCtoGs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signCtoGd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoCs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoCd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoHs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoHd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneGtoCs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneGtoCd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneGtoHs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneGtoHd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneCtoGs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneCtoGd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneHtoGs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3sneHtoGd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+ options2.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signC30toGs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_00;
+ options1.max_protocol = PROTOCOL_SMB3_02;
+ options1.signing = SMB_SIGNING_REQUIRED;
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_11;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signC30toGd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_00;
+ options1.max_protocol = PROTOCOL_SMB3_02;
+ options1.signing = SMB_SIGNING_REQUIRED;
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_11;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signH2XtoGs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_OFF,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB2_02;
+ options1.max_protocol = PROTOCOL_SMB2_10;
+ options1.signing = SMB_SIGNING_REQUIRED;
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_11;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signH2XtoGd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_OFF,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB2_02;
+ options1.max_protocol = PROTOCOL_SMB2_10;
+ options1.signing = SMB_SIGNING_REQUIRED;
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_11;
+ options2.max_protocol = PROTOCOL_SMB3_11;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_NOT_SUPPORTED);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoC30s(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_00;
+ options2.max_protocol = PROTOCOL_SMB3_02;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoC30d(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB3_00;
+ options2.max_protocol = PROTOCOL_SMB3_02;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoH2Xs(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* same client guid */
+ options2 = options1;
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB2_02;
+ options2.max_protocol = PROTOCOL_SMB2_10;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_bind_negative_smb3signGtoH2Xd(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ struct smbcli_options options2;
+ bool ok;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test SMB 2.10 if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ /* different client guid */
+ options2 = options1;
+ options2.client_guid = GUID_random();
+ options2.only_negprot = true;
+ options2.min_protocol = PROTOCOL_SMB2_02;
+ options2.max_protocol = PROTOCOL_SMB2_10;
+ options2.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_bind_negative_smbXtoX(tctx, __func__,
+ credentials,
+ &options1, &options2,
+ NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
+ talloc_free(tree0);
+ return ret;
+}
+
+static bool test_session_two_logoff(struct torture_context *tctx,
+ struct smb2_tree *tree1)
+{
+ NTSTATUS status;
+ bool ret = true;
+ struct smbcli_options transport2_options;
+ struct smb2_tree *tree2 = NULL;
+ struct smb2_session *session2 = NULL;
+ struct smb2_session *session1 = tree1->session;
+ struct smb2_transport *transport1 = tree1->session->transport;
+ struct smb2_transport *transport2;
+ bool ok;
+
+ /* Connect 2nd connection */
+ torture_comment(tctx, "connect tree2 with the same client_guid\n");
+ transport2_options = transport1->options;
+ ok = torture_smb2_connection_ext(tctx, 0, &transport2_options, &tree2);
+ torture_assert(tctx, ok, "couldn't connect tree2\n");
+ transport2 = tree2->session->transport;
+ session2 = tree2->session;
+
+ torture_comment(tctx, "session2: logoff\n");
+ status = smb2_logoff(session2);
+ torture_assert_ntstatus_ok(tctx, status, "session2: logoff");
+ torture_comment(tctx, "transport2: keepalive\n");
+ status = smb2_keepalive(transport2);
+ torture_assert_ntstatus_ok(tctx, status, "transport2: keepalive");
+ torture_comment(tctx, "transport2: disconnect\n");
+ TALLOC_FREE(tree2);
+
+ torture_comment(tctx, "session1: logoff\n");
+ status = smb2_logoff(session1);
+ torture_assert_ntstatus_ok(tctx, status, "session1: logoff");
+ torture_comment(tctx, "transport1: keepalive\n");
+ status = smb2_keepalive(transport1);
+ torture_assert_ntstatus_ok(tctx, status, "transport1: keepalive");
+ torture_comment(tctx, "transport1: disconnect\n");
+ TALLOC_FREE(tree1);
+
+ return ret;
+}
+
+static bool test_session_sign_enc(struct torture_context *tctx,
+ const char *testname,
+ struct cli_credentials *credentials1,
+ const struct smbcli_options *options1)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ NTSTATUS status;
+ bool ret = false;
+ struct smb2_tree *tree1 = NULL;
+ char fname[256];
+ struct smb2_handle rh = {{0}};
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_create io1;
+ union smb_fileinfo qfinfo1;
+ union smb_notify notify;
+ struct smb2_request *req = NULL;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials1,
+ &tree1,
+ tctx->ev,
+ options1,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_connect options1 failed");
+
+ status = smb2_util_roothandle(tree1, &rh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_roothandle failed");
+
+ /* Add some random component to the file name. */
+ snprintf(fname, sizeof(fname), "%s_%s.dat",
+ testname, generate_random_str(tctx, 8));
+
+ smb2_util_unlink(tree1, fname);
+
+ smb2_oplock_create_share(&io1, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+
+ io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ status = smb2_create(tree1, tctx, &io1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed");
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ torture_assert_int_equal(tctx, io1.out.oplock_level,
+ smb2_util_oplock_level("b"),
+ "oplock_level incorrect");
+
+ /* Check the initial session is still alive */
+ ZERO_STRUCT(qfinfo1);
+ qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo1.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree1, tctx, &qfinfo1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ /* ask for a change notify,
+ on file or directory name changes */
+ ZERO_STRUCT(notify);
+ notify.smb2.level = RAW_NOTIFY_SMB2;
+ notify.smb2.in.buffer_size = 1000;
+ notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+ notify.smb2.in.file.handle = rh;
+ notify.smb2.in.recursive = true;
+
+ req = smb2_notify_send(tree1, &(notify.smb2));
+ WAIT_FOR_ASYNC_RESPONSE(req);
+
+ status = smb2_cancel(req);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_cancel failed");
+
+ status = smb2_notify_recv(req, tctx, &(notify.smb2));
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_CANCELLED,
+ ret, done,
+ "smb2_notify_recv failed");
+
+ /* Check the initial session is still alive */
+ ZERO_STRUCT(qfinfo1);
+ qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo1.generic.in.file.handle = _h1;
+ status = smb2_getinfo_file(tree1, tctx, &qfinfo1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ ret = true;
+done:
+ if (h1 != NULL) {
+ smb2_util_close(tree1, *h1);
+ }
+ TALLOC_FREE(tree1);
+
+ return ret;
+}
+
+static bool test_session_signing_hmac_sha_256(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test signing only if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_HMAC_SHA256,
+ },
+ };
+
+ ret = test_session_sign_enc(tctx,
+ __func__,
+ credentials,
+ &options1);
+ TALLOC_FREE(tree0);
+ return ret;
+}
+
+static bool test_session_signing_aes_128_cmac(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test signing only if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_CMAC,
+ },
+ };
+
+ ret = test_session_sign_enc(tctx,
+ __func__,
+ credentials,
+ &options1);
+ TALLOC_FREE(tree0);
+ return ret;
+}
+
+static bool test_session_signing_aes_128_gmac(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials = samba_cmdline_get_creds();
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ bool encrypted;
+
+ encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli);
+ if (encrypted) {
+ torture_skip(tctx,
+ "Can't test signing only if encrytion is required");
+ }
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_SIGNING_AES128_GMAC,
+ },
+ };
+
+ ret = test_session_sign_enc(tctx,
+ __func__,
+ credentials,
+ &options1);
+ TALLOC_FREE(tree0);
+ return ret;
+}
+
+static bool test_session_encryption_aes_128_ccm(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_CCM,
+ },
+ };
+
+ ret = test_session_sign_enc(tctx,
+ __func__,
+ credentials,
+ &options1);
+ TALLOC_FREE(tree0);
+ return ret;
+}
+
+static bool test_session_encryption_aes_128_gcm(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES128_GCM,
+ },
+ };
+
+ ret = test_session_sign_enc(tctx,
+ __func__,
+ credentials,
+ &options1);
+ TALLOC_FREE(tree0);
+ return ret;
+}
+
+static bool test_session_encryption_aes_256_ccm(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES256_CCM,
+ },
+ };
+
+ ret = test_session_sign_enc(tctx,
+ __func__,
+ credentials,
+ &options1);
+ TALLOC_FREE(tree0);
+ return ret;
+}
+
+static bool test_session_encryption_aes_256_gcm(struct torture_context *tctx, struct smb2_tree *tree0)
+{
+ struct cli_credentials *credentials0 = samba_cmdline_get_creds();
+ struct cli_credentials *credentials = NULL;
+ bool ret = false;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct smbcli_options options1;
+ bool ok;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 support");
+ }
+
+ if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) {
+ torture_skip(tctx,
+ "Can't test without SMB 3.1.1 signing negotiation support");
+ }
+
+ credentials = cli_credentials_shallow_copy(tctx, credentials0);
+ torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(credentials,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options1 = transport0->options;
+ options1.client_guid = GUID_random();
+ options1.min_protocol = PROTOCOL_SMB3_11;
+ options1.max_protocol = PROTOCOL_SMB3_11;
+ options1.signing = SMB_SIGNING_REQUIRED;
+ options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) {
+ .num_algos = 1,
+ .algos = {
+ SMB2_ENCRYPTION_AES256_GCM,
+ },
+ };
+
+ ret = test_session_sign_enc(tctx,
+ __func__,
+ credentials,
+ &options1);
+ TALLOC_FREE(tree0);
+ return ret;
+}
+
+static bool test_session_ntlmssp_bug14932(struct torture_context *tctx, struct smb2_tree *tree)
+{
+ struct cli_credentials *ntlm_creds =
+ cli_credentials_shallow_copy(tctx, samba_cmdline_get_creds());
+ NTSTATUS status;
+ bool ret = true;
+ /*
+ * This is a NTLMv2_RESPONSE with the strange
+ * NTLMv2_CLIENT_CHALLENGE used by the net diag
+ * tool.
+ *
+ * As we expect an error anyway we fill the
+ * Response part with 0xab...
+ */
+ static const char *netapp_magic =
+ "\xab\xab\xab\xab\xab\xab\xab\xab"
+ "\xab\xab\xab\xab\xab\xab\xab\xab"
+ "\x01\x01\x00\x00\x00\x00\x00\x00"
+ "\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f"
+ "\xb8\x82\x3a\xf1\xb3\xdd\x08\x15"
+ "\x00\x00\x00\x00\x11\xa2\x08\x81"
+ "\x50\x38\x22\x78\x2b\x94\x47\xfe"
+ "\x54\x94\x7b\xff\x17\x27\x5a\xb4"
+ "\xf4\x18\xba\xdc\x2c\x38\xfd\x5b"
+ "\xfb\x0e\xc1\x85\x1e\xcc\x92\xbb"
+ "\x9b\xb1\xc4\xd5\x53\x14\xff\x8c"
+ "\x76\x49\xf5\x45\x90\x19\xa2";
+ DATA_BLOB lm_response = data_blob_talloc_zero(tctx, 24);
+ DATA_BLOB lm_session_key = data_blob_talloc_zero(tctx, 16);
+ DATA_BLOB nt_response = data_blob_const(netapp_magic, 95);
+ DATA_BLOB nt_session_key = data_blob_talloc_zero(tctx, 16);
+
+ cli_credentials_set_kerberos_state(ntlm_creds,
+ CRED_USE_KERBEROS_DISABLED,
+ CRED_SPECIFIED);
+ cli_credentials_set_ntlm_response(ntlm_creds,
+ &lm_response,
+ &lm_session_key,
+ &nt_response,
+ &nt_session_key,
+ CRED_SPECIFIED);
+ status = smb2_session_setup_spnego(tree->session,
+ ntlm_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER,
+ "smb2_session_setup_spnego failed");
+
+ return ret;
+}
+
+struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite =
+ torture_suite_create(ctx, "session");
+
+ torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
+ torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
+ torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
+ torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
+ torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
+ torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
+ torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
+ torture_suite_add_1smb2_test(suite, "reauth6", test_session_reauth6);
+ torture_suite_add_simple_test(suite, "expire1n", test_session_expire1n);
+ torture_suite_add_simple_test(suite, "expire1s", test_session_expire1s);
+ torture_suite_add_simple_test(suite, "expire1e", test_session_expire1e);
+ torture_suite_add_simple_test(suite, "expire2s", test_session_expire2s);
+ torture_suite_add_simple_test(suite, "expire2e", test_session_expire2e);
+ torture_suite_add_simple_test(suite, "expire_disconnect",
+ test_session_expire_disconnect);
+ torture_suite_add_1smb2_test(suite, "bind1", test_session_bind1);
+ torture_suite_add_1smb2_test(suite, "bind2", test_session_bind2);
+ torture_suite_add_1smb2_test(suite, "bind_invalid_auth", test_session_bind_invalid_auth);
+ torture_suite_add_1smb2_test(suite, "bind_different_user", test_session_bind_different_user);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb202", test_session_bind_negative_smb202);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb210s", test_session_bind_negative_smb210s);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb210d", test_session_bind_negative_smb210d);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb2to3s", test_session_bind_negative_smb2to3s);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb2to3d", test_session_bind_negative_smb2to3d);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3to2s", test_session_bind_negative_smb3to2s);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3to2d", test_session_bind_negative_smb3to2d);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3to3s", test_session_bind_negative_smb3to3s);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3to3d", test_session_bind_negative_smb3to3d);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3encGtoCs", test_session_bind_negative_smb3encGtoCs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3encGtoCd", test_session_bind_negative_smb3encGtoCd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signCtoHs", test_session_bind_negative_smb3signCtoHs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signCtoHd", test_session_bind_negative_smb3signCtoHd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signCtoGs", test_session_bind_negative_smb3signCtoGs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signCtoGd", test_session_bind_negative_smb3signCtoGd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signHtoCs", test_session_bind_negative_smb3signHtoCs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signHtoCd", test_session_bind_negative_smb3signHtoCd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signHtoGs", test_session_bind_negative_smb3signHtoGs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signHtoGd", test_session_bind_negative_smb3signHtoGd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoCs", test_session_bind_negative_smb3signGtoCs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoCd", test_session_bind_negative_smb3signGtoCd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoHs", test_session_bind_negative_smb3signGtoHs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoHd", test_session_bind_negative_smb3signGtoHd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneGtoCs", test_session_bind_negative_smb3sneGtoCs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneGtoCd", test_session_bind_negative_smb3sneGtoCd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneGtoHs", test_session_bind_negative_smb3sneGtoHs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneGtoHd", test_session_bind_negative_smb3sneGtoHd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneCtoGs", test_session_bind_negative_smb3sneCtoGs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneCtoGd", test_session_bind_negative_smb3sneCtoGd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneHtoGs", test_session_bind_negative_smb3sneHtoGs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3sneHtoGd", test_session_bind_negative_smb3sneHtoGd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signC30toGs", test_session_bind_negative_smb3signC30toGs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signC30toGd", test_session_bind_negative_smb3signC30toGd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signH2XtoGs", test_session_bind_negative_smb3signH2XtoGs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signH2XtoGd", test_session_bind_negative_smb3signH2XtoGd);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoC30s", test_session_bind_negative_smb3signGtoC30s);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoC30d", test_session_bind_negative_smb3signGtoC30d);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoH2Xs", test_session_bind_negative_smb3signGtoH2Xs);
+ torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoH2Xd", test_session_bind_negative_smb3signGtoH2Xd);
+ torture_suite_add_1smb2_test(suite, "two_logoff", test_session_two_logoff);
+ torture_suite_add_1smb2_test(suite, "signing-hmac-sha-256", test_session_signing_hmac_sha_256);
+ torture_suite_add_1smb2_test(suite, "signing-aes-128-cmac", test_session_signing_aes_128_cmac);
+ torture_suite_add_1smb2_test(suite, "signing-aes-128-gmac", test_session_signing_aes_128_gmac);
+ torture_suite_add_1smb2_test(suite, "encryption-aes-128-ccm", test_session_encryption_aes_128_ccm);
+ torture_suite_add_1smb2_test(suite, "encryption-aes-128-gcm", test_session_encryption_aes_128_gcm);
+ torture_suite_add_1smb2_test(suite, "encryption-aes-256-ccm", test_session_encryption_aes_256_ccm);
+ torture_suite_add_1smb2_test(suite, "encryption-aes-256-gcm", test_session_encryption_aes_256_gcm);
+ torture_suite_add_1smb2_test(suite, "ntlmssp_bug14932", test_session_ntlmssp_bug14932);
+
+ suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
+
+ return suite;
+}
+
+static bool test_session_require_sign_bug15397(struct torture_context *tctx,
+ struct smb2_tree *_tree)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ struct cli_credentials *_creds = samba_cmdline_get_creds();
+ struct cli_credentials *creds = NULL;
+ struct smbcli_options options;
+ struct smb2_tree *tree = NULL;
+ uint8_t security_mode;
+ NTSTATUS status;
+ bool ok = true;
+
+ /*
+ * Setup our own connection so we can control the signing flags
+ */
+
+ creds = cli_credentials_shallow_copy(tctx, _creds);
+ torture_assert(tctx, creds != NULL, "cli_credentials_shallow_copy");
+
+ options = _tree->session->transport->options;
+ options.client_guid = GUID_random();
+ options.signing = SMB_SIGNING_IF_REQUIRED;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ creds,
+ &tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
+ torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
+ "smb2_connect failed");
+
+ security_mode = smb2cli_session_security_mode(tree->session->smbXcli);
+
+ torture_assert_int_equal_goto(
+ tctx,
+ security_mode,
+ SMB2_NEGOTIATE_SIGNING_REQUIRED | SMB2_NEGOTIATE_SIGNING_ENABLED,
+ ok,
+ done,
+ "Signing not required");
+
+done:
+ return ok;
+}
+
+struct torture_suite *torture_smb2_session_req_sign_init(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite =
+ torture_suite_create(ctx, "session-require-signing");
+
+ torture_suite_add_1smb2_test(suite, "bug15397",
+ test_session_require_sign_bug15397);
+
+ suite->description = talloc_strdup(suite, "SMB2-SESSION require signing tests");
+ return suite;
+}