1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00
samba-mirror/source4/torture/smb2/session.c
Stefan Metzmacher f6009aa73b s4:torture/smb2: let smb2.session.expire2* also check compound requests
This shows that all compound related requests should get
NT_STATUS_NETWORK_SESSION_EXPIRED.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15696

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
2024-08-13 21:13:33 +00:00

6356 lines
199 KiB
C

/*
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"
/* Ticket lifetime we want to request in seconds */
#define KRB5_TICKET_LIFETIME 5
/* Allowed clock skew in seconds */
#define KRB5_CLOCKSKEW 5
/* Time till ticket fully expired in seconds */
#define KRB5_TICKET_EXPIRETIME KRB5_TICKET_LIFETIME + KRB5_CLOCKSKEW
#define texpand(x) #x
#define GENSEC_GSSAPI_REQUESTED_LIFETIME(x) \
"gensec_gssapi:requested_life_time=" texpand(x)
#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; \
} \
}
static void sleep_remaining(struct torture_context *tctx,
const struct timeval *endtime)
{
struct timeval current = tevent_timeval_current();
double remaining_secs = timeval_elapsed2(&current, endtime);
remaining_secs = remaining_secs < 1.0 ? 1.0 : remaining_secs;
torture_comment(
tctx,
"sleep for %2.f second(s) that the krb5 ticket expires",
remaining_secs);
smb_msleep((int)(remaining_secs * 1000));
}
/**
* 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;
struct timeval endtime;
bool ticket_expired = false;
use_kerberos = cli_credentials_get_kerberos_state(credentials);
if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
torture_warning(tctx,
"smb2.session.expire1 requires "
"--use-kerberos=required!");
torture_skip(tctx,
"smb2.session.expire1 requires "
"--use-kerberos=required!");
}
torture_assert_int_equal(tctx,
use_kerberos,
CRED_USE_KERBEROS_REQUIRED,
"please use --use-kerberos=required");
cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
lpcfg_set_option(
tctx->lp_ctx,
GENSEC_GSSAPI_REQUESTED_LIFETIME(KRB5_TICKET_LIFETIME));
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)
);
/*
* We request a ticket lifetime of KRB5_TICKET_LIFETIME seconds.
* Give the server at least KRB5_TICKET_LIFETIME + KRB5_CLOCKSKEW + a
* few more milliseconds for this to kick in.
*/
endtime = timeval_current_ofs(KRB5_TICKET_EXPIRETIME, 500 * 1000);
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, "%s: query info => OK\n",
current_timestring(tctx, true));
ZERO_STRUCT(qfinfo.access_information.out);
status = smb2_getinfo_file(tree, tctx, &qfinfo);
torture_comment(tctx, "%s: %s:%s: after smb2_getinfo_file() => %s\n",
current_timestring(tctx, true),
__location__, __func__,
nt_errstr(status));
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"smb2_getinfo_file failed");
sleep_remaining(tctx, &endtime);
torture_comment(tctx, "%s: query info => EXPIRED\n",
current_timestring(tctx, true));
ZERO_STRUCT(qfinfo.access_information.out);
status = smb2_getinfo_file(tree, tctx, &qfinfo);
torture_comment(tctx, "%s: %s:%s: after smb2_getinfo_file() => %s\n",
current_timestring(tctx, true),
__location__, __func__,
nt_errstr(status));
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, "%s: reauth => OK\n",
current_timestring(tctx, true));
status = smb2_session_setup_spnego(tree->session,
credentials,
0 /* previous_session_id */);
/*
* We request a ticket lifetime of KRB5_TICKET_LIFETIME seconds.
* Give the server at least KRB5_TICKET_LIFETIME +
* KRB5_CLOCKSKEW + a few more milliseconds for this to kick in.
*/
endtime = timeval_current_ofs(KRB5_TICKET_EXPIRETIME,
500 * 1000);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"smb2_session_setup_spnego failed");
smb2cli_session_require_signed_response(
tree->session->smbXcli, false);
}
ticket_expired = timeval_expired(&endtime);
if (ticket_expired) {
struct timeval current = timeval_current();
double remaining_secs = timeval_elapsed2(&current, &endtime);
remaining_secs = remaining_secs < 0.0 ? remaining_secs * -1.0
: remaining_secs;
torture_warning(
tctx,
"The ticket already expired %.2f seconds ago. "
"You might want to increase KRB5_TICKET_LIFETIME.",
remaining_secs);
}
torture_assert(tctx,
ticket_expired == false,
"The kerberos ticket already expired");
ZERO_STRUCT(qfinfo.access_information.out);
torture_comment(tctx, "%s: %s:%s: before smb2_getinfo_file()\n",
current_timestring(tctx, true),
__location__, __func__);
status = smb2_getinfo_file(tree, tctx, &qfinfo);
torture_comment(tctx, "%s: %s:%s: after smb2_getinfo_file() => %s\n",
current_timestring(tctx, true),
__location__, __func__,
nt_errstr(status));
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_LIFETIME(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 relhandle = { .data = { UINT64_MAX, UINT64_MAX } };
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_create cio;
struct smb2_find fnd;
struct smb2_close cl;
struct smb2_request *reqs[3] = { NULL, };
union smb_search_data *d = NULL;
unsigned int count;
struct smb2_request *req = NULL;
struct smb2_notify ntf1;
struct smb2_notify ntf2;
struct timeval endtime;
use_kerberos = cli_credentials_get_kerberos_state(credentials);
if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
torture_warning(tctx,
"smb2.session.expire1 requires "
"--use-kerberos=required!");
torture_skip(tctx,
"smb2.session.expire1 requires "
"--use-kerberos=required!");
}
torture_assert_int_equal(tctx,
use_kerberos,
CRED_USE_KERBEROS_REQUIRED,
"please use --use-kerberos=required");
cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
lpcfg_set_option(
tctx->lp_ctx,
GENSEC_GSSAPI_REQUESTED_LIFETIME(KRB5_TICKET_LIFETIME));
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)
);
/*
* We request a ticket lifetime of KRB5_TICKET_LIFETIME seconds.
* Give the server at least KRB5_TICKET_LIFETIME + KRB5_CLOCKSKEW + a
* few more milliseconds for this to kick in.
*/
endtime = timeval_current_ofs(KRB5_TICKET_EXPIRETIME, 500 * 1000);
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");
sleep_remaining(tctx, &endtime);
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");
/* Now do a compound open + query directory + close handle. */
smb2_transport_compound_start(tree->session->transport, 3);
torture_comment(tctx, "Compound: Open+QueryDirectory+Close => EXPIRED\n");
ZERO_STRUCT(cio);
cio.in.oplock_level = 0;
cio.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
cio.in.file_attributes = 0;
cio.in.create_disposition = NTCREATEX_DISP_OPEN;
cio.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
cio.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
cio.in.fname = "";
reqs[0] = smb2_create_send(tree, &cio);
torture_assert_not_null_goto(tctx, reqs[0], ret, done,
"smb2_create_send failed\n");
smb2_transport_compound_set_related(tree->session->transport, true);
ZERO_STRUCT(fnd);
fnd.in.file.handle = relhandle;
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;
reqs[1] = smb2_find_send(tree, &fnd);
torture_assert_not_null_goto(tctx, reqs[1], ret, done,
"smb2_find_send failed\n");
ZERO_STRUCT(cl);
cl.in.file.handle = relhandle;
reqs[2] = smb2_close_send(tree, &cl);
torture_assert_not_null_goto(tctx, reqs[2], ret, done,
"smb2_close_send failed\n");
status = smb2_create_recv(reqs[0], tree, &cio);
torture_assert_ntstatus_equal_goto(tctx, status,
NT_STATUS_NETWORK_SESSION_EXPIRED,
ret, done, "smb2_create "
"returned unexpected status");
status = smb2_find_recv(reqs[1], tree, &fnd);
torture_assert_ntstatus_equal_goto(tctx, status,
NT_STATUS_NETWORK_SESSION_EXPIRED,
ret, done, "smb2_find "
"returned unexpected status");
status = smb2_close_recv(reqs[2], &cl);
torture_assert_ntstatus_equal_goto(tctx, status,
NT_STATUS_NETWORK_SESSION_EXPIRED,
ret, done, "smb2_close "
"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_LIFETIME(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;
struct timeval endtime;
use_kerberos = cli_credentials_get_kerberos_state(credentials);
if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
torture_warning(tctx,
"smb2.session.expire1 requires "
"--use-kerberos=required!");
torture_skip(tctx,
"smb2.session.expire1 requires "
"--use-kerberos=required!");
}
cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
lpcfg_set_option(
tctx->lp_ctx,
GENSEC_GSSAPI_REQUESTED_LIFETIME(KRB5_TICKET_LIFETIME));
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)
);
/*
* We request a ticket lifetime of KRB5_TICKET_LIFETIME seconds.
* Give the server at least KRB5_TICKET_LIFETIME + KRB5_CLOCKSKEW + a
* few more milliseconds for this to kick in.
*/
endtime = timeval_current_ofs(KRB5_TICKET_EXPIRETIME, 500 * 1000);
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");
sleep_remaining(tctx, &endtime);
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_LIFETIME(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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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 encryption 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;
}
static bool test_session_anon_encryption1(struct torture_context *tctx,
struct smb2_tree *tree0)
{
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = "IPC$";
char *unc = NULL;
struct smb2_transport *transport0 = tree0->session->transport;
struct cli_credentials *anon_creds = NULL;
struct smbcli_options options;
struct smb2_transport *transport = NULL;
struct smb2_session *anon_session = NULL;
struct smb2_tree *anon_tree = NULL;
NTSTATUS status;
bool ok = true;
struct tevent_req *subreq = NULL;
uint32_t timeout_msec;
if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
torture_skip(tctx,
"Can't test without SMB3 support");
}
unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
torture_assert(tctx, unc != NULL, "talloc_asprintf");
anon_creds = cli_credentials_init_anon(tctx);
torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
ok = cli_credentials_set_smb_encryption(anon_creds,
SMB_ENCRYPTION_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
options = transport0->options;
options.client_guid = GUID_random();
options.only_negprot = true;
status = smb2_connect(tctx,
host,
lpcfg_smb_ports(tctx->lp_ctx),
share,
lpcfg_resolve_context(tctx->lp_ctx),
anon_creds,
&anon_tree,
tctx->ev,
&options,
lpcfg_socket_options(tctx->lp_ctx),
lpcfg_gensec_settings(tctx, tctx->lp_ctx));
torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
anon_session = anon_tree->session;
transport = anon_session->transport;
anon_session->anonymous_session_key = true;
smb2cli_session_torture_anonymous_encryption(anon_session->smbXcli, true);
status = smb2_session_setup_spnego(anon_session,
anon_creds,
0 /* previous_session_id */);
torture_assert_ntstatus_ok(tctx, status,
"smb2_session_setup_spnego failed");
ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
/*
* The connection is still in ConstrainedConnection state...
*
* This will use encryption and causes a connection reset
*/
timeout_msec = transport->options.request_timeout * 1000;
subreq = smb2cli_tcon_send(tctx,
tctx->ev,
transport->conn,
timeout_msec,
anon_session->smbXcli,
anon_tree->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);
if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
status = NT_STATUS_CONNECTION_RESET;
}
torture_assert_ntstatus_equal(tctx, status,
NT_STATUS_CONNECTION_RESET,
"smb2cli_tcon_recv");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, !ok, "smbXcli_conn_is_connected still connected");
return true;
}
static bool test_session_anon_encryption2(struct torture_context *tctx,
struct smb2_tree *tree0)
{
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = "IPC$";
char *unc = NULL;
struct smb2_transport *transport0 = tree0->session->transport;
struct cli_credentials *_creds = samba_cmdline_get_creds();
struct cli_credentials *user_creds = NULL;
struct cli_credentials *anon_creds = NULL;
struct smbcli_options options;
struct smb2_transport *transport = NULL;
struct smb2_session *user_session = NULL;
struct smb2_tree *user_tree = NULL;
struct smb2_session *anon_session = NULL;
struct smb2_tree *anon_tree = NULL;
struct smb2_ioctl ioctl = {
.level = RAW_IOCTL_SMB2,
.in = {
.file = {
.handle = {
.data = {
[0] = UINT64_MAX,
[1] = UINT64_MAX,
},
},
},
.function = FSCTL_QUERY_NETWORK_INTERFACE_INFO,
/* Windows client sets this to 64KiB */
.max_output_response = 0x10000,
.flags = SMB2_IOCTL_FLAG_IS_FSCTL,
},
};
NTSTATUS status;
bool ok = true;
struct tevent_req *subreq = NULL;
uint32_t timeout_msec;
uint32_t caps = smb2cli_conn_server_capabilities(transport0->conn);
NTSTATUS expected_mc_status;
if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
torture_skip(tctx,
"Can't test without SMB3 support");
}
if (caps & SMB2_CAP_MULTI_CHANNEL) {
expected_mc_status = NT_STATUS_OK;
} else {
expected_mc_status = NT_STATUS_FS_DRIVER_REQUIRED;
}
unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
torture_assert(tctx, unc != NULL, "talloc_asprintf");
user_creds = cli_credentials_shallow_copy(tctx, _creds);
torture_assert(tctx, user_creds != NULL, "cli_credentials_shallow_copy");
ok = cli_credentials_set_smb_encryption(user_creds,
SMB_ENCRYPTION_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
anon_creds = cli_credentials_init_anon(tctx);
torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
ok = cli_credentials_set_smb_encryption(anon_creds,
SMB_ENCRYPTION_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
options = transport0->options;
options.client_guid = GUID_random();
status = smb2_connect(tctx,
host,
lpcfg_smb_ports(tctx->lp_ctx),
share,
lpcfg_resolve_context(tctx->lp_ctx),
user_creds,
&user_tree,
tctx->ev,
&options,
lpcfg_socket_options(tctx->lp_ctx),
lpcfg_gensec_settings(tctx, tctx->lp_ctx));
torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
user_session = user_tree->session;
transport = user_session->transport;
ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(user)");
ok = smbXcli_session_is_authenticated(user_session->smbXcli);
torture_assert(tctx, ok, "smbXcli_session_is_authenticated(user)");
anon_session = smb2_session_init(transport,
lpcfg_gensec_settings(tctx, tctx->lp_ctx),
tctx);
torture_assert(tctx, anon_session != NULL, "smb2_session_init(anon)");
anon_session->anonymous_session_key = true;
smb2cli_session_torture_anonymous_encryption(anon_session->smbXcli, true);
status = smb2_session_setup_spnego(anon_session,
anon_creds,
0 /* previous_session_id */);
torture_assert_ntstatus_ok(tctx, status,
"smb2_session_setup_spnego failed");
ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(anon)");
ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
anon_tree = smb2_tree_init(anon_session, tctx, false);
torture_assert(tctx, anon_tree != NULL, "smb2_tree_init");
timeout_msec = transport->options.request_timeout * 1000;
subreq = smb2cli_tcon_send(tctx,
tctx->ev,
transport->conn,
timeout_msec,
anon_session->smbXcli,
anon_tree->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_ok(tctx, status,
"smb2cli_tcon_recv(anon)");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
ok = smb2cli_tcon_is_encryption_on(anon_tree->smbXcli);
torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(anon)");
ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
status = smb2_ioctl(user_tree, tctx, &ioctl);
torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
"FSCTL_QUERY_NETWORK_INTERFACE_INFO user");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
status = smb2_ioctl(anon_tree, tctx, &ioctl);
torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
"FSCTL_QUERY_NETWORK_INTERFACE_INFO anonymous");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
status = smb2_ioctl(user_tree, tctx, &ioctl);
torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
"FSCTL_QUERY_NETWORK_INTERFACE_INFO user");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
status = smb2_ioctl(anon_tree, tctx, &ioctl);
torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
"FSCTL_QUERY_NETWORK_INTERFACE_INFO anonymous");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
return true;
}
static bool test_session_anon_encryption3(struct torture_context *tctx,
struct smb2_tree *tree0)
{
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = "IPC$";
char *unc = NULL;
struct smb2_transport *transport0 = tree0->session->transport;
struct cli_credentials *_creds = samba_cmdline_get_creds();
struct cli_credentials *user_creds = NULL;
struct cli_credentials *anon_creds = NULL;
struct smbcli_options options;
struct smb2_transport *transport = NULL;
struct smb2_session *user_session = NULL;
struct smb2_tree *user_tree = NULL;
struct smb2_session *anon_session = NULL;
struct smb2_tree *anon_tree = NULL;
NTSTATUS status;
bool ok = true;
struct tevent_req *subreq = NULL;
uint32_t timeout_msec;
uint8_t wrong_session_key[16] = { 0x1f, 0x2f, 0x3f, };
if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
torture_skip(tctx,
"Can't test without SMB3 support");
}
unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
torture_assert(tctx, unc != NULL, "talloc_asprintf");
user_creds = cli_credentials_shallow_copy(tctx, _creds);
torture_assert(tctx, user_creds != NULL, "cli_credentials_shallow_copy");
ok = cli_credentials_set_smb_encryption(user_creds,
SMB_ENCRYPTION_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
anon_creds = cli_credentials_init_anon(tctx);
torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
ok = cli_credentials_set_smb_encryption(anon_creds,
SMB_ENCRYPTION_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
options = transport0->options;
options.client_guid = GUID_random();
status = smb2_connect(tctx,
host,
lpcfg_smb_ports(tctx->lp_ctx),
share,
lpcfg_resolve_context(tctx->lp_ctx),
user_creds,
&user_tree,
tctx->ev,
&options,
lpcfg_socket_options(tctx->lp_ctx),
lpcfg_gensec_settings(tctx, tctx->lp_ctx));
torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
user_session = user_tree->session;
transport = user_session->transport;
ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(user)");
ok = smbXcli_session_is_authenticated(user_session->smbXcli);
torture_assert(tctx, ok, "smbXcli_session_is_authenticated(user)");
anon_session = smb2_session_init(transport,
lpcfg_gensec_settings(tctx, tctx->lp_ctx),
tctx);
torture_assert(tctx, anon_session != NULL, "smb2_session_init(anon)");
anon_session->anonymous_session_key = true;
anon_session->forced_session_key = data_blob_const(wrong_session_key,
ARRAY_SIZE(wrong_session_key));
smb2cli_session_torture_anonymous_encryption(anon_session->smbXcli, true);
status = smb2_session_setup_spnego(anon_session,
anon_creds,
0 /* previous_session_id */);
torture_assert_ntstatus_ok(tctx, status,
"smb2_session_setup_spnego failed");
ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(anon)");
ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
anon_tree = smb2_tree_init(anon_session, tctx, false);
torture_assert(tctx, anon_tree != NULL, "smb2_tree_init");
timeout_msec = transport->options.request_timeout * 1000;
subreq = smb2cli_tcon_send(tctx,
tctx->ev,
transport->conn,
timeout_msec,
anon_session->smbXcli,
anon_tree->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);
if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
status = NT_STATUS_CONNECTION_RESET;
}
torture_assert_ntstatus_equal(tctx, status,
NT_STATUS_CONNECTION_RESET,
"smb2cli_tcon_recv");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, !ok, "smbXcli_conn_is_connected still connected");
return true;
}
static bool test_session_anon_signing1(struct torture_context *tctx,
struct smb2_tree *tree0)
{
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = "IPC$";
char *unc = NULL;
struct smb2_transport *transport0 = tree0->session->transport;
struct cli_credentials *anon_creds = NULL;
struct smbcli_options options;
struct smb2_transport *transport = NULL;
struct smb2_session *anon_session = NULL;
struct smb2_tree *anon_tree = NULL;
NTSTATUS status;
bool ok = true;
struct tevent_req *subreq = NULL;
uint32_t timeout_msec;
if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
torture_skip(tctx,
"Can't test without SMB3 support");
}
unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
torture_assert(tctx, unc != NULL, "talloc_asprintf");
anon_creds = cli_credentials_init_anon(tctx);
torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
ok = cli_credentials_set_smb_signing(anon_creds,
SMB_SIGNING_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_signing");
ok = cli_credentials_set_smb_ipc_signing(anon_creds,
SMB_SIGNING_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_ipc_signing");
ok = cli_credentials_set_smb_encryption(anon_creds,
SMB_ENCRYPTION_OFF,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
options = transport0->options;
options.client_guid = GUID_random();
options.only_negprot = true;
options.signing = SMB_SIGNING_REQUIRED;
status = smb2_connect(tctx,
host,
lpcfg_smb_ports(tctx->lp_ctx),
share,
lpcfg_resolve_context(tctx->lp_ctx),
anon_creds,
&anon_tree,
tctx->ev,
&options,
lpcfg_socket_options(tctx->lp_ctx),
lpcfg_gensec_settings(tctx, tctx->lp_ctx));
torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
anon_session = anon_tree->session;
transport = anon_session->transport;
anon_session->anonymous_session_key = true;
smb2cli_session_torture_anonymous_signing(anon_session->smbXcli, true);
status = smb2_session_setup_spnego(anon_session,
anon_creds,
0 /* previous_session_id */);
torture_assert_ntstatus_ok(tctx, status,
"smb2_session_setup_spnego failed");
ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
timeout_msec = transport->options.request_timeout * 1000;
subreq = smb2cli_tcon_send(tctx,
tctx->ev,
transport->conn,
timeout_msec,
anon_session->smbXcli,
anon_tree->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_ok(tctx, status, "smb2cli_tcon_recv");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
return true;
}
static bool test_session_anon_signing2(struct torture_context *tctx,
struct smb2_tree *tree0)
{
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = "IPC$";
char *unc = NULL;
struct smb2_transport *transport0 = tree0->session->transport;
struct cli_credentials *anon_creds = NULL;
struct smbcli_options options;
struct smb2_transport *transport = NULL;
struct smb2_session *anon_session = NULL;
struct smb2_session *anon_session_nosign = NULL;
struct smb2_tree *anon_tree = NULL;
NTSTATUS status;
bool ok = true;
struct tevent_req *subreq = NULL;
uint32_t timeout_msec;
uint8_t wrong_session_key[16] = { 0x1f, 0x2f, 0x3f, };
uint64_t session_id;
if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
torture_skip(tctx,
"Can't test without SMB3 support");
}
unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
torture_assert(tctx, unc != NULL, "talloc_asprintf");
anon_creds = cli_credentials_init_anon(tctx);
torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
ok = cli_credentials_set_smb_signing(anon_creds,
SMB_SIGNING_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_signing");
ok = cli_credentials_set_smb_ipc_signing(anon_creds,
SMB_SIGNING_REQUIRED,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_ipc_signing");
ok = cli_credentials_set_smb_encryption(anon_creds,
SMB_ENCRYPTION_OFF,
CRED_SPECIFIED);
torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
options = transport0->options;
options.client_guid = GUID_random();
options.only_negprot = true;
options.signing = SMB_SIGNING_REQUIRED;
status = smb2_connect(tctx,
host,
lpcfg_smb_ports(tctx->lp_ctx),
share,
lpcfg_resolve_context(tctx->lp_ctx),
anon_creds,
&anon_tree,
tctx->ev,
&options,
lpcfg_socket_options(tctx->lp_ctx),
lpcfg_gensec_settings(tctx, tctx->lp_ctx));
torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
anon_session = anon_tree->session;
transport = anon_session->transport;
anon_session->anonymous_session_key = true;
anon_session->forced_session_key = data_blob_const(wrong_session_key,
ARRAY_SIZE(wrong_session_key));
smb2cli_session_torture_anonymous_signing(anon_session->smbXcli, true);
smb2cli_session_torture_no_signing_disconnect(anon_session->smbXcli);
status = smb2_session_setup_spnego(anon_session,
anon_creds,
0 /* previous_session_id */);
torture_assert_ntstatus_ok(tctx, status,
"smb2_session_setup_spnego failed");
ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
/*
* create a new structure for the same session id,
* but without smb2.should_sign set.
*/
session_id = smb2cli_session_current_id(anon_session->smbXcli);
anon_session_nosign = smb2_session_init(transport,
lpcfg_gensec_settings(tctx, tctx->lp_ctx),
tctx);
torture_assert(tctx, anon_session_nosign != NULL, "smb2_session_init(anon_nosign)");
smb2cli_session_set_id_and_flags(anon_session_nosign->smbXcli, session_id, 0);
smb2cli_session_torture_no_signing_disconnect(anon_session_nosign->smbXcli);
timeout_msec = transport->options.request_timeout * 1000;
subreq = smb2cli_tcon_send(tctx,
tctx->ev,
transport->conn,
timeout_msec,
anon_session->smbXcli,
anon_tree->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(tctx, status,
NT_STATUS_ACCESS_DENIED,
"smb2cli_tcon_recv");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
subreq = smb2cli_tcon_send(tctx,
tctx->ev,
transport->conn,
timeout_msec,
anon_session_nosign->smbXcli,
anon_tree->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_ok(tctx, status, "smb2cli_tcon_recv");
ok = smbXcli_conn_is_connected(transport->conn);
torture_assert(tctx, ok, "smbXcli_conn_is_connected");
return true;
}
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);
torture_suite_add_1smb2_test(suite, "anon-encryption1", test_session_anon_encryption1);
torture_suite_add_1smb2_test(suite, "anon-encryption2", test_session_anon_encryption2);
torture_suite_add_1smb2_test(suite, "anon-encryption3", test_session_anon_encryption3);
torture_suite_add_1smb2_test(suite, "anon-signing1", test_session_anon_signing1);
torture_suite_add_1smb2_test(suite, "anon-signing2", test_session_anon_signing2);
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;
}