mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-test
(This used to be commit ece878c1f9
)
This commit is contained in:
commit
dd0da89e84
@ -48,7 +48,8 @@ static double timeval_elapsed(struct timeval *tv)
|
||||
}
|
||||
|
||||
#define torture_assert_str_equal(test, arg1, arg2, desc) \
|
||||
if (strcmp(arg1, arg2)) { \
|
||||
if (arg1 == NULL && arg2 == NULL) { \
|
||||
} else if (strcmp(arg1, arg2)) { \
|
||||
printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
|
||||
test, __location__, arg1, arg2, desc); \
|
||||
return false; \
|
||||
|
@ -1587,6 +1587,14 @@ union smb_open {
|
||||
|
||||
/* optional list of extended attributes */
|
||||
struct smb_ea_list eas;
|
||||
|
||||
struct smb2_create_blobs {
|
||||
uint32_t num_blobs;
|
||||
struct smb2_create_blob {
|
||||
const char *tag;
|
||||
DATA_BLOB data;
|
||||
} *blobs;
|
||||
} blobs;
|
||||
} in;
|
||||
struct {
|
||||
union smb_handle file;
|
||||
|
@ -121,7 +121,7 @@ static void continue_socket(struct composite_context *creq)
|
||||
struct smbcli_socket *sock;
|
||||
struct smb2_transport *transport;
|
||||
struct smb2_request *req;
|
||||
uint16_t dialects[1];
|
||||
uint16_t dialects[2];
|
||||
|
||||
c->status = smbcli_sock_connect_recv(creq, state, &sock);
|
||||
if (!composite_is_ok(c)) return;
|
||||
@ -130,11 +130,12 @@ static void continue_socket(struct composite_context *creq)
|
||||
if (composite_nomem(transport, c)) return;
|
||||
|
||||
ZERO_STRUCT(state->negprot);
|
||||
state->negprot.in.dialect_count = 1;
|
||||
state->negprot.in.dialect_count = 2;
|
||||
state->negprot.in.security_mode = 0;
|
||||
state->negprot.in.capabilities = 0;
|
||||
unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
|
||||
dialects[0] = SMB2_DIALECT_REVISION;
|
||||
dialects[0] = 0;
|
||||
dialects[1] = SMB2_DIALECT_REVISION;
|
||||
state->negprot.in.dialects = dialects;
|
||||
|
||||
req = smb2_negprot_send(transport, &state->negprot);
|
||||
|
@ -28,30 +28,59 @@
|
||||
/*
|
||||
add a blob to a smb2_create attribute blob
|
||||
*/
|
||||
NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
|
||||
const char *tag,
|
||||
DATA_BLOB add, bool last)
|
||||
static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer,
|
||||
const struct smb2_create_blob *blob,
|
||||
bool last)
|
||||
{
|
||||
uint32_t ofs = blob->length;
|
||||
size_t tag_length = strlen(tag);
|
||||
uint8_t pad = smb2_padding_size(add.length+tag_length, 8);
|
||||
if (!data_blob_realloc(mem_ctx, blob,
|
||||
blob->length + 0x14 + tag_length + add.length + pad))
|
||||
uint32_t ofs = buffer->length;
|
||||
size_t tag_length = strlen(blob->tag);
|
||||
uint8_t pad = smb2_padding_size(blob->data.length+tag_length, 4);
|
||||
|
||||
if (!data_blob_realloc(mem_ctx, buffer,
|
||||
buffer->length + 0x14 + tag_length + blob->data.length + pad))
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
|
||||
|
||||
if (last) {
|
||||
SIVAL(blob->data, ofs+0x00, 0);
|
||||
SIVAL(buffer->data, ofs+0x00, 0);
|
||||
} else {
|
||||
SIVAL(blob->data, ofs+0x00, 0x14 + tag_length + add.length + pad);
|
||||
SIVAL(buffer->data, ofs+0x00, 0x14 + tag_length + blob->data.length + pad);
|
||||
}
|
||||
SSVAL(blob->data, ofs+0x04, 0x10); /* offset of tag */
|
||||
SIVAL(blob->data, ofs+0x06, tag_length); /* tag length */
|
||||
SSVAL(blob->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */
|
||||
SIVAL(blob->data, ofs+0x0C, add.length);
|
||||
memcpy(blob->data+ofs+0x10, tag, tag_length);
|
||||
SIVAL(blob->data, ofs+0x10+tag_length, 0); /* pad? */
|
||||
memcpy(blob->data+ofs+0x14+tag_length, add.data, add.length);
|
||||
memset(blob->data+ofs+0x14+tag_length+add.length, 0, pad);
|
||||
SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */
|
||||
SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */
|
||||
SSVAL(buffer->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */
|
||||
SIVAL(buffer->data, ofs+0x0C, blob->data.length);
|
||||
memcpy(buffer->data+ofs+0x10, blob->tag, tag_length);
|
||||
SIVAL(buffer->data, ofs+0x10+tag_length, 0); /* pad? */
|
||||
memcpy(buffer->data+ofs+0x14+tag_length, blob->data.data, blob->data.length);
|
||||
memset(buffer->data+ofs+0x14+tag_length+blob->data.length, 0, pad);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b,
|
||||
const char *tag, DATA_BLOB data)
|
||||
{
|
||||
struct smb2_create_blob *array;
|
||||
|
||||
array = talloc_realloc(mem_ctx, b->blobs,
|
||||
struct smb2_create_blob,
|
||||
b->num_blobs + 1);
|
||||
NT_STATUS_HAVE_NO_MEMORY(array);
|
||||
b->blobs = array;
|
||||
|
||||
b->blobs[b->num_blobs].tag = talloc_strdup(b->blobs, tag);
|
||||
NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].tag);
|
||||
|
||||
if (data.data) {
|
||||
b->blobs[b->num_blobs].data = data_blob_talloc(b->blobs,
|
||||
data.data,
|
||||
data.length);
|
||||
NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].data.data);
|
||||
} else {
|
||||
b->blobs[b->num_blobs].data = data_blob(NULL, 0);
|
||||
}
|
||||
|
||||
b->num_blobs += 1;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -64,6 +93,7 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
|
||||
struct smb2_request *req;
|
||||
NTSTATUS status;
|
||||
DATA_BLOB blob = data_blob(NULL, 0);
|
||||
uint32_t i;
|
||||
|
||||
req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0);
|
||||
if (req == NULL) return NULL;
|
||||
@ -89,7 +119,8 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
|
||||
DATA_BLOB b = data_blob_talloc(req, NULL,
|
||||
ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas));
|
||||
ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas);
|
||||
status = smb2_create_blob_add(req, &blob, SMB2_CREATE_TAG_EXTA, b, false);
|
||||
status = smb2_create_blob_add(req, &io->in.blobs,
|
||||
SMB2_CREATE_TAG_EXTA, b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(req);
|
||||
return NULL;
|
||||
@ -99,13 +130,30 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
|
||||
|
||||
/* an empty MxAc tag seems to be used to ask the server to
|
||||
return the maximum access mask allowed on the file */
|
||||
status = smb2_create_blob_add(req, &blob, SMB2_CREATE_TAG_MXAC,
|
||||
data_blob(NULL, 0), true);
|
||||
|
||||
status = smb2_create_blob_add(req, &io->in.blobs,
|
||||
SMB2_CREATE_TAG_MXAC, data_blob(NULL, 0));
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i=0; i < io->in.blobs.num_blobs; i++) {
|
||||
bool last = false;
|
||||
const struct smb2_create_blob *c;
|
||||
|
||||
if ((i + 1) == io->in.blobs.num_blobs) {
|
||||
last = true;
|
||||
}
|
||||
|
||||
c = &io->in.blobs.blobs[i];
|
||||
status = smb2_create_blob_push_one(req, &blob,
|
||||
c, last);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(req);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
status = smb2_push_o32s32_blob(&req->out, 0x30, blob);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(req);
|
||||
|
@ -208,7 +208,21 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
|
||||
|
||||
case RAW_OPEN_SMB2:
|
||||
io->smb2.out.file.ntvfs = io2->generic.out.file.ntvfs;
|
||||
io->smb2.out.oplock_level = 0;
|
||||
switch (io2->generic.out.oplock_level) {
|
||||
case OPLOCK_BATCH:
|
||||
io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
|
||||
break;
|
||||
case OPLOCK_EXCLUSIVE:
|
||||
io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
|
||||
break;
|
||||
case OPLOCK_LEVEL_II:
|
||||
io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_II;
|
||||
break;
|
||||
default:
|
||||
io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
|
||||
break;
|
||||
}
|
||||
io->smb2.out.reserved = 0;
|
||||
io->smb2.out.create_action = io2->generic.out.create_action;
|
||||
io->smb2.out.create_time = io2->generic.out.create_time;
|
||||
io->smb2.out.access_time = io2->generic.out.access_time;
|
||||
@ -484,7 +498,18 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
|
||||
status = ntvfs->ops->open(ntvfs, req, io2);
|
||||
break;
|
||||
case RAW_OPEN_SMB2:
|
||||
io2->generic.in.flags = 0;
|
||||
switch (io->smb2.in.oplock_level) {
|
||||
case SMB2_OPLOCK_LEVEL_BATCH:
|
||||
io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK |
|
||||
NTCREATEX_FLAGS_REQUEST_OPLOCK;
|
||||
break;
|
||||
case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
|
||||
io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_OPLOCK;
|
||||
break;
|
||||
default:
|
||||
io2->generic.in.flags = 0;
|
||||
break;
|
||||
}
|
||||
io2->generic.in.root_fid = 0;
|
||||
io2->generic.in.access_mask = io->smb2.in.desired_access;
|
||||
io2->generic.in.alloc_size = 0;
|
||||
|
@ -135,7 +135,7 @@ static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
|
||||
}
|
||||
sd = *psd;
|
||||
|
||||
ids = talloc_array(sd, struct id_mapping, 2);
|
||||
ids = talloc_zero_array(sd, struct id_mapping, 2);
|
||||
NT_STATUS_HAVE_NO_MEMORY(ids);
|
||||
|
||||
ids[0].unixid = talloc(ids, struct unixid);
|
||||
|
@ -33,3 +33,11 @@ rpc.netlogon.*.GetTrustPasswords
|
||||
base.charset.*.Testing partial surrogate
|
||||
.*net.api.delshare.* # DelShare isn't implemented yet
|
||||
rap.*netservergetinfo
|
||||
smb2.persistent.handles1
|
||||
samba4.winbind.struct.*.LIST_GROUPS # Not yet working in winbind
|
||||
samba4.winbind.struct.*.SHOW_SEQUENCE # Not yet working in winbind
|
||||
samba4.winbind.struct.*.GETPWENT # Not yet working in winbind
|
||||
samba4.winbind.struct.*.SETPWENT # Not yet working in winbind
|
||||
samba4.winbind.struct.*.LOOKUP_NAME_SID # Not yet working in winbind
|
||||
|
||||
|
||||
|
@ -5,11 +5,11 @@ base.casetable
|
||||
base.nttrans
|
||||
.*base.bench.holdcon.* # Very slow
|
||||
base.scan.maxfid
|
||||
raw.hold.oplock
|
||||
raw.ping.pong
|
||||
raw.hold.oplock # Not a test, but a way to block other clients for a test
|
||||
raw.ping.pong # Needs second server to test
|
||||
rpc.samr_accessmask
|
||||
raw.scan.eamax
|
||||
raw.qfileinfo.ipc
|
||||
samba4.ntvfs.cifs.raw.qfileinfo.ipc
|
||||
base.utable
|
||||
base.smb
|
||||
smb2.notify
|
||||
@ -41,7 +41,6 @@ rpc.frsapi # Not provided by Samba 4
|
||||
.*samba3.* # Samba3-specific test
|
||||
^samba4.net.domopen.*$ # Hangs for some reason
|
||||
^samba4.net.api.become.dc.*$ # Fails
|
||||
winbind # FIXME: This should not be skipped
|
||||
nss.test # Fails
|
||||
samba4.samba3sam.python # Conversion from EJS not yet finished
|
||||
samba4.samdb.python # Not finished yet
|
||||
|
@ -27,8 +27,8 @@ class UnixinfoTests(RpcInterfaceTestCase):
|
||||
def test_getpwuid(self):
|
||||
infos = self.conn.GetPWUid(range(512))
|
||||
self.assertEquals(512, len(infos))
|
||||
self.assertEquals("", infos[0].shell)
|
||||
self.assertEquals("", infos[0].homedir)
|
||||
self.assertEquals("/bin/false", infos[0].shell)
|
||||
self.assertTrue(isinstance(infos[0].homedir, unicode))
|
||||
|
||||
def test_gidtosid(self):
|
||||
self.conn.GidToSid(1000)
|
||||
|
@ -219,13 +219,16 @@ plantest "rpc.echo on ncacn_np over smb2" dc $smb4torture ncacn_np:"\$SERVER[smb
|
||||
# Tests against the NTVFS POSIX backend
|
||||
NTVFSARGS="--option=torture:sharedelay=100000 --option=torture:oplocktimeout=3"
|
||||
smb2=`$smb4torture --list | grep "^SMB2-" | xargs`
|
||||
raw=`$smb4torture --list | grep "^RAW-" | xargs`
|
||||
#The QFILEINFO-IPC test needs to be on ipc$
|
||||
raw=`$smb4torture --list | grep "^RAW-" | grep -v "RAW-QFILEINFO-IPC"| xargs`
|
||||
base=`$smb4torture --list | grep "^BASE-" | xargs`
|
||||
|
||||
for t in $base $raw $smb2; do
|
||||
plansmbtorturetest "$t" dc $ADDARGS //\$SERVER/tmp -U"\$USERNAME"%"\$PASSWORD" $NTVFSARGS
|
||||
done
|
||||
|
||||
plansmbtorturetest "RAW-QFILEINFO-IPC" dc $ADDARGS //\$SERVER/ipc$ -U"\$USERNAME"%"\$PASSWORD"
|
||||
|
||||
rap=`$smb4torture --list | grep "^RAP-" | xargs`
|
||||
for t in $rap; do
|
||||
plansmbtorturetest "$t" dc $ADDARGS //\$SERVER/IPC\\\$ -U"\$USERNAME"%"\$PASSWORD"
|
||||
|
@ -35,6 +35,8 @@ from samba.provision import (provision,
|
||||
FILL_FULL, FILL_NT4SYNC,
|
||||
FILL_DRS)
|
||||
|
||||
# how do we make this case insensitive??
|
||||
|
||||
parser = optparse.OptionParser("provision [options]")
|
||||
sambaopts = options.SambaOptions(parser)
|
||||
parser.add_option_group(sambaopts)
|
||||
|
@ -79,6 +79,7 @@ void smb2srv_create_recv(struct smb2srv_request *req)
|
||||
SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob));
|
||||
/* TODO: parse the blob */
|
||||
ZERO_STRUCT(io->smb2.in.eas);
|
||||
ZERO_STRUCT(io->smb2.in.blobs);
|
||||
|
||||
/* the VFS backend does not yet handle NULL filenames */
|
||||
if (io->smb2.in.fname == NULL) {
|
||||
|
@ -114,9 +114,12 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
|
||||
io->out.security_mode = 0; /* no signing yet */
|
||||
io->out.dialect_revision = SMB2_DIALECT_REVISION;
|
||||
io->out.capabilities = 0;
|
||||
io->out.max_transact_size = 0x10000;
|
||||
io->out.max_read_size = 0x10000;
|
||||
io->out.max_write_size = 0x10000;
|
||||
io->out.max_transact_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL,
|
||||
"smb2", "max transaction size", 0x10000);
|
||||
io->out.max_read_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL,
|
||||
"smb2", "max read size", 0x10000);
|
||||
io->out.max_write_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL,
|
||||
"smb2", "max write size", 0x10000);
|
||||
io->out.system_time = timeval_to_nttime(¤t_time);
|
||||
io->out.server_start_time = timeval_to_nttime(&boot_time);
|
||||
io->out.reserved2 = 0;
|
||||
|
@ -36,18 +36,18 @@
|
||||
|
||||
/* global options */
|
||||
static struct gentest_options {
|
||||
bool showall;
|
||||
bool analyze;
|
||||
bool analyze_always;
|
||||
bool analyze_continuous;
|
||||
int showall;
|
||||
int analyze;
|
||||
int analyze_always;
|
||||
int analyze_continuous;
|
||||
uint_t max_open_handles;
|
||||
uint_t seed;
|
||||
uint_t numops;
|
||||
bool use_oplocks;
|
||||
int use_oplocks;
|
||||
char **ignore_patterns;
|
||||
const char *seeds_file;
|
||||
bool use_preset_seeds;
|
||||
bool fast_reconnect;
|
||||
int use_preset_seeds;
|
||||
int fast_reconnect;
|
||||
} options;
|
||||
|
||||
/* mapping between open handles on the server and local handles */
|
||||
|
@ -20,5 +20,6 @@ TORTURE_SMB2_OBJ_FILES = $(addprefix torture/smb2/, \
|
||||
find.o \
|
||||
lock.o \
|
||||
notify.o \
|
||||
smb2.o)
|
||||
smb2.o \
|
||||
persistent_handles.o)
|
||||
|
||||
|
182
source4/torture/smb2/persistent_handles.c
Normal file
182
source4/torture/smb2/persistent_handles.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
test suite for SMB2 persistent file handles
|
||||
|
||||
Copyright (C) Stefan Metzmacher 2008
|
||||
|
||||
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 "librpc/gen_ndr/security.h"
|
||||
#include "libcli/smb2/smb2.h"
|
||||
#include "libcli/smb2/smb2_calls.h"
|
||||
#include "torture/torture.h"
|
||||
#include "torture/smb2/proto.h"
|
||||
#include "param/param.h"
|
||||
|
||||
#define CHECK_VAL(v, correct) do { \
|
||||
if ((v) != (correct)) { \
|
||||
torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
|
||||
__location__, #v, (int)v, (int)correct); \
|
||||
ret = false; \
|
||||
}} while (0)
|
||||
|
||||
#define CHECK_STATUS(status, correct) do { \
|
||||
if (!NT_STATUS_EQUAL(status, correct)) { \
|
||||
torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
|
||||
nt_errstr(status), nt_errstr(correct)); \
|
||||
ret = false; \
|
||||
goto done; \
|
||||
}} while (0)
|
||||
|
||||
/*
|
||||
basic testing of SMB2 persistent file handles
|
||||
regarding the position information on the handle
|
||||
*/
|
||||
bool torture_smb2_persistent_handles1(struct torture_context *tctx,
|
||||
struct smb2_tree *tree1,
|
||||
struct smb2_tree *tree2)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_new(tctx);
|
||||
struct smb2_handle h1, h2;
|
||||
struct smb2_create io1, io2;
|
||||
NTSTATUS status;
|
||||
const char *fname = "persistent_handles.dat";
|
||||
DATA_BLOB b;
|
||||
union smb_fileinfo qfinfo;
|
||||
union smb_setfileinfo sfinfo;
|
||||
bool ret = true;
|
||||
uint64_t pos;
|
||||
|
||||
smb2_util_unlink(tree1, fname);
|
||||
|
||||
ZERO_STRUCT(io1);
|
||||
io1.in.security_flags = 0x00;
|
||||
io1.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
|
||||
io1.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
|
||||
io1.in.create_flags = 0x00000000;
|
||||
io1.in.reserved = 0x00000000;
|
||||
io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
|
||||
io1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
|
||||
io1.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
|
||||
NTCREATEX_SHARE_ACCESS_WRITE |
|
||||
NTCREATEX_SHARE_ACCESS_DELETE;
|
||||
io1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
|
||||
io1.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
|
||||
NTCREATEX_OPTIONS_ASYNC_ALERT |
|
||||
NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
|
||||
0x00200000;
|
||||
io1.in.fname = fname;
|
||||
|
||||
b = data_blob_talloc(mem_ctx, NULL, 16);
|
||||
SBVAL(b.data, 0, 0);
|
||||
SBVAL(b.data, 8, 0);
|
||||
|
||||
status = smb2_create_blob_add(tree1, &io1.in.blobs,
|
||||
SMB2_CREATE_TAG_DHNQ,
|
||||
b);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_create(tree1, mem_ctx, &io1);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
|
||||
/*CHECK_VAL(io1.out.reserved, 0);*/
|
||||
CHECK_VAL(io1.out.create_action, NTCREATEX_ACTION_CREATED);
|
||||
CHECK_VAL(io1.out.alloc_size, 0);
|
||||
CHECK_VAL(io1.out.size, 0);
|
||||
CHECK_VAL(io1.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
|
||||
CHECK_VAL(io1.out.reserved2, 0);
|
||||
|
||||
/* TODO: check extra blob content */
|
||||
|
||||
h1 = io1.out.file.handle;
|
||||
|
||||
ZERO_STRUCT(qfinfo);
|
||||
qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
|
||||
qfinfo.generic.in.file.handle = h1;
|
||||
status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_VAL(qfinfo.position_information.out.position, 0);
|
||||
pos = qfinfo.position_information.out.position;
|
||||
torture_comment(tctx, "position: %llu\n",
|
||||
(unsigned long long)pos);
|
||||
|
||||
ZERO_STRUCT(sfinfo);
|
||||
sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
|
||||
sfinfo.generic.in.file.handle = h1;
|
||||
sfinfo.position_information.in.position = 0x1000;
|
||||
status = smb2_setinfo_file(tree1, &sfinfo);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ZERO_STRUCT(qfinfo);
|
||||
qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
|
||||
qfinfo.generic.in.file.handle = h1;
|
||||
status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
|
||||
pos = qfinfo.position_information.out.position;
|
||||
torture_comment(tctx, "position: %llu\n",
|
||||
(unsigned long long)pos);
|
||||
|
||||
talloc_free(tree1);
|
||||
tree1 = NULL;
|
||||
|
||||
ZERO_STRUCT(qfinfo);
|
||||
qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
|
||||
qfinfo.generic.in.file.handle = h1;
|
||||
status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
|
||||
CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
|
||||
|
||||
ZERO_STRUCT(io2);
|
||||
io2.in.fname = fname;
|
||||
|
||||
b = data_blob_talloc(tctx, NULL, 16);
|
||||
SBVAL(b.data, 0, h1.data[0]);
|
||||
SBVAL(b.data, 8, h1.data[1]);
|
||||
|
||||
status = smb2_create_blob_add(tree2, &io2.in.blobs,
|
||||
SMB2_CREATE_TAG_DHNC,
|
||||
b);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_create(tree2, mem_ctx, &io2);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
|
||||
CHECK_VAL(io2.out.reserved, 0x00);
|
||||
CHECK_VAL(io2.out.create_action, NTCREATEX_ACTION_EXISTED);
|
||||
CHECK_VAL(io2.out.alloc_size, 0);
|
||||
CHECK_VAL(io2.out.size, 0);
|
||||
CHECK_VAL(io2.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
|
||||
CHECK_VAL(io2.out.reserved2, 0);
|
||||
|
||||
h2 = io2.out.file.handle;
|
||||
|
||||
ZERO_STRUCT(qfinfo);
|
||||
qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
|
||||
qfinfo.generic.in.file.handle = h2;
|
||||
status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
|
||||
pos = qfinfo.position_information.out.position;
|
||||
torture_comment(tctx, "position: %llu\n",
|
||||
(unsigned long long)pos);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
smb2_util_unlink(tree2, fname);
|
||||
done:
|
||||
return ret;
|
||||
}
|
@ -47,9 +47,9 @@ static bool wrap_simple_1smb2_test(struct torture_context *torture_ctx,
|
||||
}
|
||||
|
||||
struct torture_test *torture_suite_add_1smb2_test(struct torture_suite *suite,
|
||||
const char *name,
|
||||
bool (*run) (struct torture_context *,
|
||||
struct smb2_tree *))
|
||||
const char *name,
|
||||
bool (*run)(struct torture_context *,
|
||||
struct smb2_tree *))
|
||||
{
|
||||
struct torture_test *test;
|
||||
struct torture_tcase *tcase;
|
||||
@ -69,6 +69,61 @@ struct torture_test *torture_suite_add_1smb2_test(struct torture_suite *suite,
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
static bool wrap_simple_2smb2_test(struct torture_context *torture_ctx,
|
||||
struct torture_tcase *tcase,
|
||||
struct torture_test *test)
|
||||
{
|
||||
bool (*fn) (struct torture_context *, struct smb2_tree *, struct smb2_tree *);
|
||||
bool ret;
|
||||
|
||||
struct smb2_tree *tree1;
|
||||
struct smb2_tree *tree2;
|
||||
TALLOC_CTX *mem_ctx = talloc_new(torture_ctx);
|
||||
|
||||
if (!torture_smb2_connection(torture_ctx, &tree1) ||
|
||||
!torture_smb2_connection(torture_ctx, &tree2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
talloc_steal(mem_ctx, tree1);
|
||||
talloc_steal(mem_ctx, tree2);
|
||||
|
||||
fn = test->fn;
|
||||
|
||||
ret = fn(torture_ctx, tree1, tree2);
|
||||
|
||||
/* the test may already closed some of the connections */
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
_PUBLIC_ struct torture_test *torture_suite_add_2smb2_test(struct torture_suite *suite,
|
||||
const char *name,
|
||||
bool (*run)(struct torture_context *,
|
||||
struct smb2_tree *,
|
||||
struct smb2_tree *))
|
||||
{
|
||||
struct torture_test *test;
|
||||
struct torture_tcase *tcase;
|
||||
|
||||
tcase = torture_suite_add_tcase(suite, name);
|
||||
|
||||
test = talloc(tcase, struct torture_test);
|
||||
|
||||
test->name = talloc_strdup(test, name);
|
||||
test->description = NULL;
|
||||
test->run = wrap_simple_2smb2_test;
|
||||
test->fn = run;
|
||||
test->dangerous = false;
|
||||
|
||||
DLIST_ADD_END(tcase->tests, test, struct torture_test *);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
NTSTATUS torture_smb2_init(void)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "SMB2");
|
||||
@ -82,6 +137,7 @@ NTSTATUS torture_smb2_init(void)
|
||||
torture_suite_add_simple_test(suite, "FIND", torture_smb2_find);
|
||||
torture_suite_add_suite(suite, torture_smb2_lock_init());
|
||||
torture_suite_add_simple_test(suite, "NOTIFY", torture_smb2_notify);
|
||||
torture_suite_add_2smb2_test(suite, "PERSISTENT-HANDLES1", torture_smb2_persistent_handles1);
|
||||
|
||||
suite->description = talloc_strdup(suite, "SMB2-specific tests");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user