1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00
samba-mirror/source4/torture/raw/session.c
Stefan Metzmacher 9c44f40b8d s4:torture/raw: add raw.session.expire1
This demonstrates the interaction of CAP_DYNAMIC_REAUTH
and NT_STATUS_NETWORK_SESSION_EXPIRED.

metze
2012-06-22 12:56:48 +02:00

436 lines
15 KiB
C

/*
Unix SMB/CIFS implementation.
test suite for session setup operations
Copyright (C) Gregor Beck 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 "torture.h"
#include "smb_cli.h"
#include "torture/raw/proto.h"
#include "smb_composite/smb_composite.h"
#include "lib/cmdline/popt_common.h"
#include "param/param.h"
#include "torture/util.h"
#include "auth/credentials/credentials.h"
#include "libcli/resolve/resolve.h"
static bool test_session_reauth1(struct torture_context *tctx,
struct smbcli_state *cli)
{
NTSTATUS status;
struct smb_composite_sesssetup io;
int fnum, num;
const int dlen = 255;
char *data;
char fname[256];
char buf[dlen+1];
bool ok = true;
uint16_t vuid1 = cli->session->vuid;
data = generate_random_str(tctx, dlen);
torture_assert(tctx, (data != NULL), "memory allocation failed");
snprintf(fname, sizeof(fname), "raw_session_reconnect_%.8s.dat", data);
fnum = smbcli_nt_create_full(cli->tree, fname, 0,
SEC_RIGHTS_FILE_ALL,
FILE_ATTRIBUTE_NORMAL,
NTCREATEX_SHARE_ACCESS_NONE,
NTCREATEX_DISP_OPEN_IF,
NTCREATEX_OPTIONS_DELETE_ON_CLOSE,
0);
torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ok,
done, "create file");
torture_assert_goto(tctx, fnum > 0, ok, done, "create file");
num = smbcli_smbwrite(cli->tree, fnum, data, 0, dlen);
torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "write file");
ZERO_STRUCT(io);
io.in.sesskey = cli->transport->negotiate.sesskey;
io.in.capabilities = cli->transport->negotiate.capabilities;
io.in.credentials = cmdline_credentials;
io.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
io.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
status = smb_composite_sesssetup(cli->session, &io);
torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "setup2");
torture_assert_int_equal_goto(tctx, io.out.vuid, vuid1, ok, done, "setup2");
num = smbcli_read(cli->tree, fnum, &buf, 0, dlen);
torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "read file");
torture_assert_str_equal_goto(tctx, buf, data, ok, done, "read file");
done:
talloc_free(data);
if (fnum > 0) {
status = smbcli_close(cli->tree, fnum);
torture_assert_ntstatus_ok(tctx, status, "close");
}
return ok;
}
static bool test_session_reauth2_oplock_timeout(
struct smbcli_transport *transport, uint16_t tid, uint16_t fnum,
uint8_t level, void *private_data)
{
return true;
}
static bool test_session_reauth2(struct torture_context *tctx,
struct smbcli_state *cli)
{
char *random_string;
char *fname;
union smb_open io_open;
struct smb_composite_sesssetup io_sesssetup;
union smb_fileinfo io_qsecdesc;
struct smbcli_request *req;
struct cli_credentials *anon_creds;
NTSTATUS status;
uint16_t fnum;
ssize_t nwritten;
uint16_t vuid1 = cli->session->vuid;
random_string = generate_random_str(tctx, 8);
torture_assert(tctx, (random_string != NULL),
"memory allocation failed");
fname = talloc_asprintf(tctx, "raw_session_reauth2_%s.dat",
random_string);
talloc_free(random_string);
torture_assert(tctx, (fname != NULL), "memory allocation failed");
smbcli_unlink(cli->tree, fname);
smbcli_oplock_handler(cli->transport,
test_session_reauth2_oplock_timeout,
cli->tree);
/*
base ntcreatex parms
*/
ZERO_STRUCT(io_open);
io_open.generic.level = RAW_OPEN_NTCREATEX;
io_open.ntcreatex.in.root_fid.fnum = 0;
io_open.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
io_open.ntcreatex.in.alloc_size = 0;
io_open.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
io_open.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
io_open.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
io_open.ntcreatex.in.create_options = 0;
io_open.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
io_open.ntcreatex.in.security_flags = 0;
io_open.ntcreatex.in.fname = fname;
torture_comment(tctx, "open with batch oplock\n");
io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
status = smb_raw_open(cli->tree, tctx, &io_open);
torture_assert_ntstatus_ok(tctx, status, "smb_raw_open failed");
fnum = io_open.ntcreatex.out.file.fnum;
torture_assert(
tctx,
(io_open.ntcreatex.out.oplock_level == BATCH_OPLOCK_RETURN),
"did not get batch oplock");
io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
req = smb_raw_open_send(cli->tree, &io_open);
torture_assert(tctx, (req != NULL), "memory allocation failed");
/*
* Make sure the open went through
*/
status = smbcli_chkpath(cli->tree, "\\");
torture_assert_ntstatus_ok(tctx, status, "smb_chkpath failed");
status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
"close");
anon_creds = cli_credentials_init_anon(tctx);
torture_assert(tctx, (anon_creds != NULL), "memory allocation failed");
ZERO_STRUCT(io_sesssetup);
io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey;
io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
io_sesssetup.in.credentials = anon_creds;
io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(
tctx, tctx->lp_ctx);
status = smb_composite_sesssetup(cli->session, &io_sesssetup);
torture_assert_ntstatus_ok(tctx, status, "setup2 failed");
torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2");
status = smbcli_close(cli->tree, fnum);
torture_assert_ntstatus_ok(tctx, status, "close failed");
status = smb_raw_open_recv(req, tctx, &io_open);
torture_assert_ntstatus_ok(tctx, status, "2nd open failed");
fnum = io_open.ntcreatex.out.file.fnum;
nwritten = smbcli_write(cli->tree, fnum, 0, fname, 0, strlen(fname));
torture_assert(tctx, (nwritten == strlen(fname)),
"smbcli_write failed");
ZERO_STRUCT(io_qsecdesc);
io_qsecdesc.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
io_qsecdesc.query_secdesc.in.file.fnum = fnum;
io_qsecdesc.query_secdesc.in.secinfo_flags = SECINFO_OWNER;
status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc);
torture_assert_ntstatus_equal(
tctx, status, NT_STATUS_ACCESS_DENIED,
"anon qsecdesc did not return ACCESS_DENIED");
ZERO_STRUCT(io_sesssetup);
io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey;
io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
io_sesssetup.in.credentials = cmdline_credentials;
io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(
tctx, tctx->lp_ctx);
status = smb_composite_sesssetup(cli->session, &io_sesssetup);
torture_assert_ntstatus_ok(tctx, status, "setup3 failed");
torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2");
status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc);
torture_assert_ntstatus_ok(tctx, status, "2nd qsecdesc failed");
status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
"close");
status = smbcli_close(cli->tree, fnum);
torture_assert_ntstatus_ok(tctx, status, "close failed");
return true;
}
static bool test_session_expire1(struct torture_context *tctx)
{
NTSTATUS status;
bool ret = false;
struct smbcli_options options;
struct smbcli_session_options session_options;
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = torture_setting_string(tctx, "share", NULL);
struct cli_credentials *credentials = cmdline_credentials;
struct smbcli_state *cli = NULL;
enum credentials_use_kerberos use_kerberos;
char fname[256];
union smb_fileinfo qfinfo;
uint16_t vuid;
uint16_t fnum;
struct smb_composite_sesssetup io_sesssetup;
size_t i;
use_kerberos = cli_credentials_get_kerberos_state(credentials);
if (use_kerberos != CRED_MUST_USE_KERBEROS) {
torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
}
torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
"please use -k yes");
lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
lpcfg_smbcli_options(tctx->lp_ctx, &options);
lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
status = smbcli_full_connection(tctx, &cli,
host,
lpcfg_smb_ports(tctx->lp_ctx),
share, NULL,
lpcfg_socket_options(tctx->lp_ctx),
credentials,
lpcfg_resolve_context(tctx->lp_ctx),
tctx->ev, &options, &session_options,
lpcfg_gensec_settings(tctx, tctx->lp_ctx));
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"smbcli_full_connection failed");
vuid = cli->session->vuid;
/* Add some random component to the file name. */
snprintf(fname, 256, "session_expire1_%s.dat",
generate_random_str(tctx, 8));
smbcli_unlink(cli->tree, fname);
fnum = smbcli_nt_create_full(cli->tree, fname, 0,
SEC_RIGHTS_FILE_ALL,
FILE_ATTRIBUTE_NORMAL,
NTCREATEX_SHARE_ACCESS_NONE,
NTCREATEX_DISP_OPEN_IF,
NTCREATEX_OPTIONS_DELETE_ON_CLOSE,
0);
torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ret,
done, "create file");
torture_assert_goto(tctx, fnum > 0, ret, done, "create file");
/* get the access information */
ZERO_STRUCT(qfinfo);
qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
qfinfo.access_information.in.file.fnum = fnum;
for (i=0; i < 2; i++) {
torture_comment(tctx, "query info => OK\n");
ZERO_STRUCT(qfinfo.access_information.out);
status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"raw_fileinfo failed");
torture_comment(tctx, "sleep 5 seconds\n");
smb_msleep(5*1000);
}
/*
* the krb5 library may not handle expired creds
* well, lets start with an empty ccache.
*/
cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
/*
* now with CAP_DYNAMIC_REAUTH
*
* This should trigger NT_STATUS_NETWORK_SESSION_EXPIRED
*/
ZERO_STRUCT(io_sesssetup);
io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey;
io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
io_sesssetup.in.capabilities |= CAP_DYNAMIC_REAUTH;
io_sesssetup.in.credentials = credentials;
io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(tctx,
tctx->lp_ctx);
torture_comment(tctx, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
ZERO_STRUCT(io_sesssetup.out);
status = smb_composite_sesssetup(cli->session, &io_sesssetup);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"reauth failed");
torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
ret, done, "reauth");
for (i=0; i < 2; i++) {
torture_comment(tctx, "query info => OK\n");
ZERO_STRUCT(qfinfo.access_information.out);
status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"raw_fileinfo failed");
torture_comment(tctx, "sleep 5 seconds\n");
smb_msleep(5*1000);
torture_comment(tctx, "query info => EXPIRED\n");
ZERO_STRUCT(qfinfo.access_information.out);
status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
torture_assert_ntstatus_equal_goto(tctx, status,
NT_STATUS_NETWORK_SESSION_EXPIRED,
ret, done, "raw_fileinfo expired");
/*
* the krb5 library may not handle expired creds
* well, lets start with an empty ccache.
*/
cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
torture_comment(tctx, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
ZERO_STRUCT(io_sesssetup.out);
status = smb_composite_sesssetup(cli->session, &io_sesssetup);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"reauth failed");
torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
ret, done, "reauth");
}
torture_comment(tctx, "query info => OK\n");
ZERO_STRUCT(qfinfo.access_information.out);
status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"raw_fileinfo failed");
/*
* the krb5 library may not handle expired creds
* well, lets start with an empty ccache.
*/
cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
/*
* now without CAP_DYNAMIC_REAUTH
*
* This should not trigger NT_STATUS_NETWORK_SESSION_EXPIRED
*/
torture_comment(tctx, "reauth without CAP_DYNAMIC_REAUTH => OK\n");
io_sesssetup.in.capabilities &= ~CAP_DYNAMIC_REAUTH;
ZERO_STRUCT(io_sesssetup.out);
status = smb_composite_sesssetup(cli->session, &io_sesssetup);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"reauth failed");
torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
ret, done, "reauth");
for (i=0; i < 2; i++) {
torture_comment(tctx, "query info => OK\n");
ZERO_STRUCT(qfinfo.access_information.out);
status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"raw_fileinfo failed");
torture_comment(tctx, "sleep 5 seconds\n");
smb_msleep(5*1000);
}
torture_comment(tctx, "query info => OK\n");
ZERO_STRUCT(qfinfo.access_information.out);
status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
"raw_fileinfo failed");
ret = true;
done:
if (fnum > 0) {
smbcli_close(cli->tree, fnum);
}
talloc_free(cli);
lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
return ret;
}
struct torture_suite *torture_raw_session(TALLOC_CTX *mem_ctx)
{
struct torture_suite *suite = torture_suite_create(mem_ctx, "session");
suite->description = talloc_strdup(suite, "RAW-SESSION tests");
torture_suite_add_1smb_test(suite, "reauth1", test_session_reauth1);
torture_suite_add_1smb_test(suite, "reauth2", test_session_reauth2);
torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
return suite;
}