summaryrefslogtreecommitdiff
path: root/source4/torture
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture')
-rw-r--r--source4/torture/gentest.c2
-rw-r--r--source4/torture/gentest_smb2.c462
-rw-r--r--source4/torture/locktest.c2
-rw-r--r--source4/torture/masktest.c2
-rw-r--r--source4/torture/raw/read.c17
-rw-r--r--source4/torture/raw/streams.c95
-rw-r--r--source4/torture/smb2/config.mk4
-rw-r--r--source4/torture/smb2/connect.c6
-rw-r--r--source4/torture/smb2/create.c201
-rw-r--r--source4/torture/smb2/getinfo.c12
-rw-r--r--source4/torture/smb2/lock.c110
-rw-r--r--source4/torture/smb2/read.c141
-rw-r--r--source4/torture/smb2/smb2.c2
-rw-r--r--source4/torture/smbtorture.c29
14 files changed, 847 insertions, 238 deletions
diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c
index ae18fe809c..cd33074b4f 100644
--- a/source4/torture/gentest.c
+++ b/source4/torture/gentest.c
@@ -30,7 +30,7 @@
#include "libcli/resolve/resolve.h"
#include "auth/gensec/gensec.h"
#include "param/param.h"
-#include "dynconfig.h"
+#include "dynconfig/dynconfig.h"
#define NSERVERS 2
#define NINSTANCES 2
diff --git a/source4/torture/gentest_smb2.c b/source4/torture/gentest_smb2.c
index fc6dbcbb9a..3e705dc60d 100644
--- a/source4/torture/gentest_smb2.c
+++ b/source4/torture/gentest_smb2.c
@@ -34,7 +34,7 @@
#include "libcli/resolve/resolve.h"
#include "auth/gensec/gensec.h"
#include "param/param.h"
-#include "dynconfig.h"
+#include "dynconfig/dynconfig.h"
#define NSERVERS 2
#define NINSTANCES 2
@@ -53,6 +53,9 @@ static struct gentest_options {
const char *seeds_file;
int use_preset_seeds;
int fast_reconnect;
+ int mask_indexing;
+ int no_eas;
+ int skip_cleanup;
} options;
/* mapping between open handles on the server and local handles */
@@ -110,7 +113,8 @@ static struct smb2_handle bad_smb2_handle;
#define BAD_HANDLE 0xFFFE
-static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private);
+static bool oplock_handler(struct smb2_transport *transport, const struct smb2_handle *handle,
+ uint8_t level, void *private_data);
static void idle_func(struct smb2_transport *transport, void *private);
/*
@@ -206,7 +210,8 @@ static bool connect_servers(struct event_context *ev,
return false;
}
-// smb2_oplock_handler(servers[i].cli[j]->transport, oplock_handler, NULL);
+ servers[i].tree[j]->session->transport->oplock.handler = oplock_handler;
+ servers[i].tree[j]->session->transport->oplock.private_data = (void *)(uintptr_t)((i<<8)|j);
smb2_transport_idle_handler(servers[i].tree[j]->session->transport, idle_func, 50000, NULL);
}
}
@@ -510,24 +515,37 @@ static uint32_t gen_bits_mask2(uint32_t mask1, uint32_t mask2)
}
/*
- generate a boolean
-*/
-static bool gen_bool(void)
+ generate reserved values
+ */
+static uint64_t gen_reserved8(void)
{
- return gen_bits_mask2(0x1, 0xFF);
+ return gen_bits_mask(0xFF);
}
-/*
- generate ntrename flags
-*/
-static uint16_t gen_rename_flags(void)
+static uint64_t gen_reserved16(void)
{
- if (gen_chance(30)) return RENAME_FLAG_RENAME;
- if (gen_chance(30)) return RENAME_FLAG_HARD_LINK;
- if (gen_chance(30)) return RENAME_FLAG_COPY;
return gen_bits_mask(0xFFFF);
}
+static uint64_t gen_reserved32(void)
+{
+ return gen_bits_mask(0xFFFFFFFF);
+}
+
+static uint64_t gen_reserved64(void)
+{
+ return gen_bits_mask(0xFFFFFFFF) | (((uint64_t)gen_bits_mask(0xFFFFFFFF))<<32);
+}
+
+
+
+/*
+ generate a boolean
+*/
+static bool gen_bool(void)
+{
+ return gen_bits_mask2(0x1, 0xFF);
+}
/*
return a set of lock flags
@@ -543,15 +561,6 @@ static uint16_t gen_lock_flags(void)
}
/*
- generate a pid
-*/
-static uint16_t gen_pid(void)
-{
- if (gen_chance(10)) return gen_bits_mask(0xFFFF);
- return getpid();
-}
-
-/*
generate a lock count
*/
static off_t gen_lock_count(void)
@@ -560,15 +569,6 @@ static off_t gen_lock_count(void)
}
/*
- generate a ntcreatex flags field
-*/
-static uint32_t gen_ntcreatex_flags(void)
-{
- if (gen_chance(70)) return NTCREATEX_FLAGS_EXTENDED;
- return gen_bits_mask2(0x1F, 0xFFFFFFFF);
-}
-
-/*
generate a NT access mask
*/
static uint32_t gen_access_mask(void)
@@ -599,34 +599,6 @@ static uint32_t gen_open_disp(void)
}
/*
- generate an openx open mode
-*/
-static uint16_t gen_openx_mode(void)
-{
- if (gen_chance(20)) return gen_bits_mask(0xFFFF);
- if (gen_chance(20)) return gen_bits_mask(0xFF);
- return OPENX_MODE_DENY_NONE | gen_bits_mask(0x3);
-}
-
-/*
- generate an openx flags field
-*/
-static uint16_t gen_openx_flags(void)
-{
- if (gen_chance(20)) return gen_bits_mask(0xFFFF);
- return gen_bits_mask(0x7);
-}
-
-/*
- generate an openx open function
-*/
-static uint16_t gen_openx_func(void)
-{
- if (gen_chance(20)) return gen_bits_mask(0xFFFF);
- return gen_bits_mask(0x13);
-}
-
-/*
generate a file attrib combination
*/
static uint32_t gen_attrib(void)
@@ -655,15 +627,6 @@ static NTTIME gen_nttime(void)
}
/*
- generate a milliseconds protocol timeout
-*/
-static uint32_t gen_timeout(void)
-{
- if (gen_chance(98)) return 0;
- return random() % 50;
-}
-
-/*
generate a file allocation size
*/
static uint_t gen_alloc_size(void)
@@ -721,6 +684,126 @@ static struct ea_struct gen_ea_struct(void)
}
/*
+ generate an ea_struct
+*/
+static struct smb_ea_list gen_ea_list(void)
+{
+ struct smb_ea_list eas;
+ int i;
+ if (options.no_eas) {
+ ZERO_STRUCT(eas);
+ return eas;
+ }
+ eas.num_eas = gen_int_range(0, 3);
+ eas.eas = talloc_array(current_op.mem_ctx, struct ea_struct, eas.num_eas);
+ for (i=0;i<eas.num_eas;i++) {
+ eas.eas[i] = gen_ea_struct();
+ }
+ return eas;
+}
+
+static void oplock_handler_close_recv(struct smb2_request *req)
+{
+ NTSTATUS status;
+ struct smb2_close io;
+ status = smb2_close_recv(req, &io);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("close failed in oplock_handler\n");
+ smb_panic("close failed in oplock_handler");
+ }
+}
+
+static void oplock_handler_ack_callback(struct smb2_request *req)
+{
+ NTSTATUS status;
+ struct smb2_break br;
+
+ status = smb2_break_recv(req, &br);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("oplock break ack failed in oplock_handler\n");
+ smb_panic("oplock break ack failed in oplock_handler");
+ }
+}
+
+static bool send_oplock_ack(struct smb2_tree *tree, struct smb2_handle handle,
+ uint8_t level)
+{
+ struct smb2_break br;
+ struct smb2_request *req;
+
+ ZERO_STRUCT(br);
+ br.in.file.handle = handle;
+ br.in.oplock_level = level;
+ br.in.reserved = gen_reserved8();
+ br.in.reserved2 = gen_reserved32();
+
+ req = smb2_break_send(tree, &br);
+ if (req == NULL) return false;
+ req->async.fn = oplock_handler_ack_callback;
+ req->async.private_data = NULL;
+ return true;
+}
+
+/*
+ the oplock handler will either ack the break or close the file
+*/
+static bool oplock_handler(struct smb2_transport *transport, const struct smb2_handle *handle,
+ uint8_t level, void *private_data)
+{
+ struct smb2_close io;
+ unsigned i, j;
+ bool do_close;
+ struct smb2_tree *tree = NULL;
+ struct smb2_request *req;
+
+ srandom(current_op.seed);
+ do_close = gen_chance(50);
+
+ i = ((uintptr_t)private_data) >> 8;
+ j = ((uintptr_t)private_data) & 0xFF;
+
+ if (i >= NSERVERS || j >= NINSTANCES) {
+ printf("Bad private_data in oplock_handler\n");
+ return false;
+ }
+
+ oplocks[i][j].got_break = true;
+ oplocks[i][j].server_handle = *handle;
+ oplocks[i][j].handle = fnum_to_handle(i, j, *handle);
+ oplocks[i][j].level = level;
+ oplocks[i][j].do_close = do_close;
+ tree = talloc_get_type(servers[i].tree[j], struct smb2_tree);
+
+ if (!tree) {
+ printf("Oplock break not for one of our trees!?\n");
+ return false;
+ }
+
+ if (!do_close) {
+ printf("oplock ack handle=%d\n", oplocks[i][j].handle);
+ return send_oplock_ack(tree, *handle, level);
+ }
+
+ printf("oplock close fnum=%d\n", oplocks[i][j].handle);
+
+ ZERO_STRUCT(io);
+ io.in.file.handle = *handle;
+ io.in.flags = 0;
+ req = smb2_close_send(tree, &io);
+
+ if (req == NULL) {
+ printf("WARNING: close failed in oplock_handler_close\n");
+ return false;
+ }
+
+ req->async.fn = oplock_handler_close_recv;
+ req->async.private_data = NULL;
+
+ return true;
+}
+
+
+/*
the idle function tries to cope with getting an oplock break on a connection, and
an operation on another connection blocking until that break is acked
we check for operations on all transports in the idle function
@@ -758,7 +841,7 @@ static bool compare_status(NTSTATUS status1, NTSTATUS status2)
return false;
}
-
+#if 0
/*
check for pending packets on all connections
*/
@@ -774,6 +857,7 @@ static void check_pending(void)
}
}
}
+#endif
/*
check that the same oplock breaks have been received by all instances
@@ -953,6 +1037,16 @@ again:
#define CHECK_EQUAL(field) do { \
if (parm[0].field != parm[1].field && !ignore_pattern(#field)) { \
+ printf("Mismatch in %s - 0x%llx 0x%llx\n", #field, \
+ (unsigned long long)parm[0].field, (unsigned long long)parm[1].field); \
+ return false; \
+ } \
+} while(0)
+
+#define CHECK_ATTRIB(field) do { \
+ if (!options.mask_indexing) { \
+ CHECK_EQUAL(field); \
+ } else if ((~FILE_ATTRIBUTE_NONINDEXED & parm[0].field) != (~FILE_ATTRIBUTE_NONINDEXED & parm[1].field) && !ignore_pattern(#field)) { \
printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
(int)parm[0].field, (int)parm[1].field); \
return false; \
@@ -980,15 +1074,6 @@ again:
CHECK_EQUAL(field.length); \
} while(0)
-#define CHECK_TIMES_EQUAL(field) do { \
- if (labs(parm[0].field - parm[1].field) > time_skew() && \
- !ignore_pattern(#field)) { \
- printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
- (int)parm[0].field, (int)parm[1].field); \
- return false; \
- } \
-} while(0)
-
#define CHECK_NTTIMES_EQUAL(field) do { \
if (labs(nt_time_to_unix(parm[0].field) - \
nt_time_to_unix(parm[1].field)) > time_skew() && \
@@ -1016,22 +1101,20 @@ static bool handler_create(int instance)
if (gen_chance(2)) {
parm[0].in.create_flags |= gen_bits_mask(0xFFFFFFFF);
}
- parm[0].in.reserved = gen_bits_levels(2, 95, 0x0, 100, 0xFFFFFFFF);
- if (gen_chance(2)) {
- parm[0].in.reserved |= gen_bits_mask(0xFFFFFFFF);
- }
+ parm[0].in.reserved = gen_reserved64();
parm[0].in.desired_access = gen_access_mask();
parm[0].in.file_attributes = gen_attrib();
parm[0].in.share_access = gen_bits_mask2(0x7, 0xFFFFFFFF);
parm[0].in.create_disposition = gen_open_disp();
parm[0].in.create_options = gen_create_options();
parm[0].in.fname = gen_fname_open(instance);
+ parm[0].in.eas = gen_ea_list();
if (!options.use_oplocks) {
/* mask out oplocks */
parm[0].in.oplock_level = 0;
}
-
+
GEN_COPY_PARM;
GEN_CALL(smb2_create(tree, current_op.mem_ctx, &parm[i]));
@@ -1044,7 +1127,7 @@ static bool handler_create(int instance)
CHECK_NTTIMES_EQUAL(out.change_time);
CHECK_EQUAL(out.alloc_size);
CHECK_EQUAL(out.size);
- CHECK_EQUAL(out.file_attr);
+ CHECK_ATTRIB(out.file_attr);
CHECK_EQUAL(out.reserved2);
/* ntcreatex creates a new file handle */
@@ -1077,7 +1160,7 @@ static bool handler_close(int instance)
CHECK_NTTIMES_EQUAL(out.change_time);
CHECK_EQUAL(out.alloc_size);
CHECK_EQUAL(out.size);
- CHECK_EQUAL(out.file_attr);
+ CHECK_ATTRIB(out.file_attr);
REMOVE_HANDLE(in.file.handle);
@@ -1093,7 +1176,7 @@ static bool handler_read(int instance)
NTSTATUS status[NSERVERS];
parm[0].in.file.handle.data[0] = gen_fnum(instance);
- parm[0].in.reserved = gen_bits_mask2(0x0, 0xFF);
+ parm[0].in.reserved = gen_reserved8();
parm[0].in.length = gen_io_count();
parm[0].in.offset = gen_offset();
parm[0].in.min_count = gen_io_count();
@@ -1151,7 +1234,7 @@ static bool handler_lock(int instance)
parm[0].level = RAW_LOCK_LOCKX;
parm[0].in.file.handle.data[0] = gen_fnum(instance);
parm[0].in.lock_count = gen_lock_count();
- parm[0].in.reserved = gen_bits_mask2(0, 0xFFFFFFFF);
+ parm[0].in.reserved = gen_reserved32();
parm[0].in.locks = talloc_array(current_op.mem_ctx,
struct smb2_lock_element,
@@ -1182,8 +1265,8 @@ static bool handler_flush(int instance)
ZERO_STRUCT(parm[0]);
parm[0].in.file.handle.data[0] = gen_fnum(instance);
- parm[0].in.reserved1 = gen_bits_mask2(0x0, 0xFFFF);
- parm[0].in.reserved2 = gen_bits_mask2(0x0, 0xFFFFFFFF);
+ parm[0].in.reserved1 = gen_reserved16();
+ parm[0].in.reserved2 = gen_reserved32();
GEN_COPY_PARM;
GEN_SET_FNUM(in.file.handle);
@@ -1194,7 +1277,19 @@ static bool handler_flush(int instance)
return true;
}
-#if 0
+/*
+ generate echo operations
+*/
+static bool handler_echo(int instance)
+{
+ NTSTATUS status[NSERVERS];
+
+ GEN_CALL(smb2_keepalive(tree->session->transport));
+
+ return true;
+}
+
+
/*
generate a fileinfo query structure
@@ -1207,16 +1302,13 @@ static void gen_fileinfo(int instance, union smb_fileinfo *info)
enum smb_fileinfo_level level;
const char *name;
} levels[] = {
- LVL(GETATTR), LVL(GETATTRE), LVL(STANDARD),
- LVL(EA_SIZE), LVL(ALL_EAS), LVL(IS_NAME_VALID),
- LVL(BASIC_INFO), LVL(STANDARD_INFO), LVL(EA_INFO),
- LVL(NAME_INFO), LVL(ALL_INFO), LVL(ALT_NAME_INFO),
- LVL(STREAM_INFO), LVL(COMPRESSION_INFO), LVL(BASIC_INFORMATION),
+ LVL(BASIC_INFORMATION),
LVL(STANDARD_INFORMATION), LVL(INTERNAL_INFORMATION), LVL(EA_INFORMATION),
LVL(ACCESS_INFORMATION), LVL(NAME_INFORMATION), LVL(POSITION_INFORMATION),
- LVL(MODE_INFORMATION), LVL(ALIGNMENT_INFORMATION), LVL(ALL_INFORMATION),
+ LVL(MODE_INFORMATION), LVL(ALIGNMENT_INFORMATION), LVL(SMB2_ALL_INFORMATION),
LVL(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION),
- LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION)
+ LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION),
+ LVL(SMB2_ALL_EAS), LVL(SMB2_ALL_INFORMATION),
};
do {
i = gen_int_range(0, ARRAY_SIZE(levels)-1);
@@ -1238,62 +1330,31 @@ static bool cmp_fileinfo(int instance,
case RAW_FILEINFO_GENERIC:
return false;
+ /* SMB1 specific values */
case RAW_FILEINFO_GETATTR:
- CHECK_EQUAL(getattr.out.attrib);
- CHECK_EQUAL(getattr.out.size);
- CHECK_TIMES_EQUAL(getattr.out.write_time);
- break;
-
case RAW_FILEINFO_GETATTRE:
- CHECK_TIMES_EQUAL(getattre.out.create_time);
- CHECK_TIMES_EQUAL(getattre.out.access_time);
- CHECK_TIMES_EQUAL(getattre.out.write_time);
- CHECK_EQUAL(getattre.out.size);
- CHECK_EQUAL(getattre.out.alloc_size);
- CHECK_EQUAL(getattre.out.attrib);
- break;
-
case RAW_FILEINFO_STANDARD:
- CHECK_TIMES_EQUAL(standard.out.create_time);
- CHECK_TIMES_EQUAL(standard.out.access_time);
- CHECK_TIMES_EQUAL(standard.out.write_time);
- CHECK_EQUAL(standard.out.size);
- CHECK_EQUAL(standard.out.alloc_size);
- CHECK_EQUAL(standard.out.attrib);
- break;
-
case RAW_FILEINFO_EA_SIZE:
- CHECK_TIMES_EQUAL(ea_size.out.create_time);
- CHECK_TIMES_EQUAL(ea_size.out.access_time);
- CHECK_TIMES_EQUAL(ea_size.out.write_time);
- CHECK_EQUAL(ea_size.out.size);
- CHECK_EQUAL(ea_size.out.alloc_size);
- CHECK_EQUAL(ea_size.out.attrib);
- CHECK_EQUAL(ea_size.out.ea_size);
- break;
-
case RAW_FILEINFO_ALL_EAS:
- CHECK_EQUAL(all_eas.out.num_eas);
- for (i=0;i<parm[0].all_eas.out.num_eas;i++) {
- CHECK_EQUAL(all_eas.out.eas[i].flags);
- CHECK_WSTR_EQUAL(all_eas.out.eas[i].name);
- CHECK_BLOB_EQUAL(all_eas.out.eas[i].value);
- }
- break;
-
case RAW_FILEINFO_IS_NAME_VALID:
- break;
-
case RAW_FILEINFO_BASIC_INFO:
+ case RAW_FILEINFO_STANDARD_INFO:
+ case RAW_FILEINFO_EA_INFO:
+ case RAW_FILEINFO_NAME_INFO:
+ case RAW_FILEINFO_ALL_INFO:
+ case RAW_FILEINFO_ALT_NAME_INFO:
+ case RAW_FILEINFO_STREAM_INFO:
+ case RAW_FILEINFO_COMPRESSION_INFO:
+ return false;
+
case RAW_FILEINFO_BASIC_INFORMATION:
CHECK_NTTIMES_EQUAL(basic_info.out.create_time);
CHECK_NTTIMES_EQUAL(basic_info.out.access_time);
CHECK_NTTIMES_EQUAL(basic_info.out.write_time);
CHECK_NTTIMES_EQUAL(basic_info.out.change_time);
- CHECK_EQUAL(basic_info.out.attrib);
+ CHECK_ATTRIB(basic_info.out.attrib);
break;
- case RAW_FILEINFO_STANDARD_INFO:
case RAW_FILEINFO_STANDARD_INFORMATION:
CHECK_EQUAL(standard_info.out.alloc_size);
CHECK_EQUAL(standard_info.out.size);
@@ -1302,38 +1363,18 @@ static bool cmp_fileinfo(int instance,
CHECK_EQUAL(standard_info.out.directory);
break;
- case RAW_FILEINFO_EA_INFO:
case RAW_FILEINFO_EA_INFORMATION:
CHECK_EQUAL(ea_info.out.ea_size);
break;
- case RAW_FILEINFO_NAME_INFO:
case RAW_FILEINFO_NAME_INFORMATION:
CHECK_WSTR_EQUAL(name_info.out.fname);
break;
- case RAW_FILEINFO_ALL_INFO:
- case RAW_FILEINFO_ALL_INFORMATION:
- CHECK_NTTIMES_EQUAL(all_info.out.create_time);
- CHECK_NTTIMES_EQUAL(all_info.out.access_time);
- CHECK_NTTIMES_EQUAL(all_info.out.write_time);
- CHECK_NTTIMES_EQUAL(all_info.out.change_time);
- CHECK_EQUAL(all_info.out.attrib);
- CHECK_EQUAL(all_info.out.alloc_size);
- CHECK_EQUAL(all_info.out.size);
- CHECK_EQUAL(all_info.out.nlink);
- CHECK_EQUAL(all_info.out.delete_pending);
- CHECK_EQUAL(all_info.out.directory);
- CHECK_EQUAL(all_info.out.ea_size);
- CHECK_WSTR_EQUAL(all_info.out.fname);
- break;
-
- case RAW_FILEINFO_ALT_NAME_INFO:
case RAW_FILEINFO_ALT_NAME_INFORMATION:
CHECK_WSTR_EQUAL(alt_name_info.out.fname);
break;
- case RAW_FILEINFO_STREAM_INFO:
case RAW_FILEINFO_STREAM_INFORMATION:
CHECK_EQUAL(stream_info.out.num_streams);
for (i=0;i<parm[0].stream_info.out.num_streams;i++) {
@@ -1343,7 +1384,6 @@ static bool cmp_fileinfo(int instance,
}
break;
- case RAW_FILEINFO_COMPRESSION_INFO:
case RAW_FILEINFO_COMPRESSION_INFORMATION:
CHECK_EQUAL(compression_info.out.compressed_size);
CHECK_EQUAL(compression_info.out.format);
@@ -1379,22 +1419,51 @@ static bool cmp_fileinfo(int instance,
CHECK_NTTIMES_EQUAL(network_open_information.out.change_time);
CHECK_EQUAL(network_open_information.out.alloc_size);
CHECK_EQUAL(network_open_information.out.size);
- CHECK_EQUAL(network_open_information.out.attrib);
+ CHECK_ATTRIB(network_open_information.out.attrib);
break;
case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
- CHECK_EQUAL(attribute_tag_information.out.attrib);
+ CHECK_ATTRIB(attribute_tag_information.out.attrib);
CHECK_EQUAL(attribute_tag_information.out.reparse_tag);
break;
+ case RAW_FILEINFO_ALL_INFORMATION:
+ case RAW_FILEINFO_SMB2_ALL_INFORMATION:
+ CHECK_NTTIMES_EQUAL(all_info2.out.create_time);
+ CHECK_NTTIMES_EQUAL(all_info2.out.access_time);
+ CHECK_NTTIMES_EQUAL(all_info2.out.write_time);
+ CHECK_NTTIMES_EQUAL(all_info2.out.change_time);
+ CHECK_ATTRIB(all_info2.out.attrib);
+ CHECK_EQUAL(all_info2.out.unknown1);
+ CHECK_EQUAL(all_info2.out.alloc_size);
+ CHECK_EQUAL(all_info2.out.size);
+ CHECK_EQUAL(all_info2.out.nlink);
+ CHECK_EQUAL(all_info2.out.delete_pending);
+ CHECK_EQUAL(all_info2.out.directory);
+ CHECK_EQUAL(all_info2.out.file_id);
+ CHECK_EQUAL(all_info2.out.ea_size);
+ CHECK_EQUAL(all_info2.out.access_mask);
+ CHECK_EQUAL(all_info2.out.position);
+ CHECK_EQUAL(all_info2.out.mode);
+ CHECK_EQUAL(all_info2.out.alignment_requirement);
+ CHECK_WSTR_EQUAL(all_info2.out.fname);
+ break;
+
+ case RAW_FILEINFO_SMB2_ALL_EAS:
+ CHECK_EQUAL(all_eas.out.num_eas);
+ for (i=0;i<parm[0].all_eas.out.num_eas;i++) {
+ CHECK_EQUAL(all_eas.out.eas[i].flags);
+ CHECK_WSTR_EQUAL(all_eas.out.eas[i].name);
+ CHECK_BLOB_EQUAL(all_eas.out.eas[i].value);
+ }
+ break;
+
/* Unhandled levels */
case RAW_FILEINFO_SEC_DESC:
case RAW_FILEINFO_EA_LIST:
case RAW_FILEINFO_UNIX_BASIC:
case RAW_FILEINFO_UNIX_LINK:
- case RAW_FILEINFO_SMB2_ALL_EAS:
- case RAW_FILEINFO_SMB2_ALL_INFORMATION:
case RAW_FILEINFO_UNIX_INFO2:
break;
}
@@ -1410,13 +1479,13 @@ static bool handler_qfileinfo(int instance)
union smb_fileinfo parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].generic.in.file.fnum = gen_fnum(instance);
+ parm[0].generic.in.file.handle.data[0] = gen_fnum(instance);
gen_fileinfo(instance, &parm[0]);
GEN_COPY_PARM;
- GEN_SET_FNUM(generic.in.file.fnum);
- GEN_CALL(smb_raw_fileinfo(tree, current_op.mem_ctx, &parm[i]));
+ GEN_SET_FNUM(generic.in.file.handle);
+ GEN_CALL(smb2_getinfo_file(tree, current_op.mem_ctx, &parm[i]));
return cmp_fileinfo(instance, parm, status);
}
@@ -1434,12 +1503,7 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
enum smb_setfileinfo_level level;
const char *name;
} levels[] = {
-#if 0
- /* disabled until win2003 can handle them ... */
- LVL(EA_SET), LVL(BASIC_INFO), LVL(DISPOSITION_INFO),
- LVL(STANDARD), LVL(ALLOCATION_INFO), LVL(END_OF_FILE_INFO),
-#endif
- LVL(SETATTR), LVL(SETATTRE), LVL(BASIC_INFORMATION),
+ LVL(BASIC_INFORMATION),
LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION),
LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
@@ -1453,27 +1517,15 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
switch (info->generic.level) {
case RAW_SFILEINFO_SETATTR:
- info->setattr.in.attrib = gen_attrib();
- info->setattr.in.write_time = gen_timet();
- break;
case RAW_SFILEINFO_SETATTRE:
- info->setattre.in.create_time = gen_timet();
- info->setattre.in.access_time = gen_timet();
- info->setattre.in.write_time = gen_timet();
- break;
case RAW_SFILEINFO_STANDARD:
- info->standard.in.create_time = gen_timet();
- info->standard.in.access_time = gen_timet();
- info->standard.in.write_time = gen_timet();
- break;
- case RAW_SFILEINFO_EA_SET: {
- static struct ea_struct ea;
- info->ea_set.in.num_eas = 1;
- info->ea_set.in.eas = &ea;
- info->ea_set.in.eas[0] = gen_ea_struct();
- }
- break;
+ case RAW_SFILEINFO_EA_SET:
case RAW_SFILEINFO_BASIC_INFO:
+ case RAW_SFILEINFO_DISPOSITION_INFO:
+ case RAW_SFILEINFO_END_OF_FILE_INFO:
+ case RAW_SFILEINFO_ALLOCATION_INFO:
+ break;
+
case RAW_SFILEINFO_BASIC_INFORMATION:
info->basic_info.in.create_time = gen_nttime();
info->basic_info.in.access_time = gen_nttime();
@@ -1481,15 +1533,12 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
info->basic_info.in.change_time = gen_nttime();
info->basic_info.in.attrib = gen_attrib();
break;
- case RAW_SFILEINFO_DISPOSITION_INFO:
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
info->disposition_info.in.delete_on_close = gen_bool();
break;
- case RAW_SFILEINFO_ALLOCATION_INFO:
case RAW_SFILEINFO_ALLOCATION_INFORMATION:
info->allocation_info.in.alloc_size = gen_alloc_size();
break;
- case RAW_SFILEINFO_END_OF_FILE_INFO:
case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
info->end_of_file_info.in.size = gen_offset();
break;
@@ -1507,16 +1556,16 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
break;
case RAW_SFILEINFO_GENERIC:
case RAW_SFILEINFO_SEC_DESC:
- case RAW_SFILEINFO_UNIX_BASIC:
- case RAW_SFILEINFO_UNIX_LINK:
- case RAW_SFILEINFO_UNIX_HLINK:
case RAW_SFILEINFO_1023:
case RAW_SFILEINFO_1025:
case RAW_SFILEINFO_1029:
case RAW_SFILEINFO_1032:
case RAW_SFILEINFO_1039:
case RAW_SFILEINFO_1040:
+ case RAW_SFILEINFO_UNIX_BASIC:
case RAW_SFILEINFO_UNIX_INFO2:
+ case RAW_SFILEINFO_UNIX_LINK:
+ case RAW_SFILEINFO_UNIX_HLINK:
/* Untested */
break;
}
@@ -1535,15 +1584,12 @@ static bool handler_sfileinfo(int instance)
gen_setfileinfo(instance, &parm[0]);
GEN_COPY_PARM;
- GEN_SET_FNUM(generic.in.file.fnum);
- GEN_CALL(smb_raw_setfileinfo(tree, &parm[i]));
+ GEN_SET_FNUM(generic.in.file.handle);
+ GEN_CALL(smb2_setinfo_file(tree, &parm[i]));
return true;
}
-#endif
-
-
/*
wipe any relevant files
*/
@@ -1552,6 +1598,10 @@ static void wipe_files(void)
int i;
NTSTATUS status;
+ if (options.skip_cleanup) {
+ return;
+ }
+
for (i=0;i<NSERVERS;i++) {
int n = smb2_deltree(servers[i].tree[0], "gentest");
if (n == -1) {
@@ -1606,6 +1656,9 @@ static struct {
{"WRITE", handler_write},
{"LOCK", handler_lock},
{"FLUSH", handler_flush},
+ {"ECHO", handler_echo},
+ {"QFILEINFO", handler_qfileinfo},
+ {"SFILEINFO", handler_sfileinfo},
};
@@ -1870,6 +1923,9 @@ static bool split_unc_name(const char *unc, char **server, char **share)
{"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
{"seedsfile", 0, POPT_ARG_STRING, &options.seeds_file, 0, "seed file", NULL},
{ "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
+ {"maskindexing", 0, POPT_ARG_NONE, &options.mask_indexing, 0, "mask out the indexed file attrib", NULL},
+ {"noeas", 0, POPT_ARG_NONE, &options.no_eas, 0, "don't use extended attributes", NULL},
+ {"skip-cleanup", 0, POPT_ARG_NONE, &options.skip_cleanup, 0, "don't delete files at start", NULL},
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
diff --git a/source4/torture/locktest.c b/source4/torture/locktest.c
index 8959232edb..4a0dfc2a6f 100644
--- a/source4/torture/locktest.c
+++ b/source4/torture/locktest.c
@@ -27,7 +27,7 @@
#include "auth/gensec/gensec.h"
#include "libcli/libcli.h"
#include "param/param.h"
-#include "dynconfig.h"
+#include "dynconfig/dynconfig.h"
#include "libcli/resolve/resolve.h"
static int numops = 1000;
diff --git a/source4/torture/masktest.c b/source4/torture/masktest.c
index 39b1296dbe..255d94382c 100644
--- a/source4/torture/masktest.c
+++ b/source4/torture/masktest.c
@@ -28,7 +28,7 @@
#include "auth/credentials/credentials.h"
#include "auth/gensec/gensec.h"
#include "param/param.h"
-#include "dynconfig.h"
+#include "dynconfig/dynconfig.h"
#include "libcli/resolve/resolve.h"
#include "lib/events/events.h"
diff --git a/source4/torture/raw/read.c b/source4/torture/raw/read.c
index c8420c279e..ada9b1f432 100644
--- a/source4/torture/raw/read.c
+++ b/source4/torture/raw/read.c
@@ -460,6 +460,23 @@ static bool test_readx(struct torture_context *tctx, struct smbcli_state *cli)
CHECK_VALUE(io.readx.out.compaction_mode, 0);
}
+ printf("Trying mincnt past EOF\n");
+ memset(buf, 0, maxsize);
+ io.readx.in.offset = 0;
+ io.readx.in.mincnt = 100;
+ io.readx.in.maxcnt = 110;
+ status = smb_raw_read(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
+ CHECK_VALUE(io.readx.out.compaction_mode, 0);
+ CHECK_VALUE(io.readx.out.nread, strlen(test_data));
+ if (memcmp(buf, test_data, strlen(test_data)) != 0) {
+ ret = false;
+ printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
+ goto done;
+ }
+
+
setup_buffer(buf, seed, maxsize);
smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
memset(buf, 0, maxsize);
diff --git a/source4/torture/raw/streams.c b/source4/torture/raw/streams.c
index 1dab36c28b..8b2d327653 100644
--- a/source4/torture/raw/streams.c
+++ b/source4/torture/raw/streams.c
@@ -135,6 +135,11 @@ static bool check_stream_list(struct smbcli_state *cli, const char *fname,
goto fail;
}
+ if (num_exp == 0) {
+ ret = true;
+ goto fail;
+ }
+
exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
if (exp_sort == NULL) {
@@ -170,7 +175,81 @@ static bool check_stream_list(struct smbcli_state *cli, const char *fname,
}
/*
- test basic io on streams
+ test bahavior of streams on directories
+*/
+static bool test_stream_dir(struct torture_context *tctx,
+ struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+ NTSTATUS status;
+ union smb_open io;
+ const char *fname = BASEDIR "\\stream.txt";
+ const char *sname1;
+ bool ret = true;
+ const char *basedir_data;
+
+ basedir_data = talloc_asprintf(mem_ctx, "%s::$DATA", BASEDIR);
+ sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One");
+
+ printf("(%s) opening non-existant directory stream\n", __location__);
+ io.generic.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.flags = 0;
+ io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
+ io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ io.ntcreatex.in.share_access = 0;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = sname1;
+ status = smb_raw_open(cli->tree, mem_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
+
+ printf("(%s) opening basedir stream\n", __location__);
+ io.generic.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.flags = 0;
+ io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
+ io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
+ io.ntcreatex.in.share_access = 0;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = basedir_data;
+ status = smb_raw_open(cli->tree, mem_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
+
+ printf("(%s) opening basedir ::$DATA stream\n", __location__);
+ io.generic.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.flags = 0x10;
+ io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
+ io.ntcreatex.in.create_options = 0;
+ io.ntcreatex.in.file_attr = 0;
+ io.ntcreatex.in.share_access = 0;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = basedir_data;
+ status = smb_raw_open(cli->tree, mem_ctx, &io);
+ if (torture_setting_bool(tctx, "samba3", false)) {
+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ } else {
+ CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
+ }
+
+ printf("(%s) list the streams on the basedir\n", __location__);
+ ret &= check_stream_list(cli, BASEDIR, 0, NULL);
+done:
+ return ret;
+}
+
+/*
+ test basic behavior of streams on directories
*/
static bool test_stream_io(struct torture_context *tctx,
struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
@@ -191,12 +270,12 @@ static bool test_stream_io(struct torture_context *tctx,
sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One");
sname2 = talloc_asprintf(mem_ctx, "%s:%s:$DaTa", fname, "Second Stream");
- printf("(%s) opening non-existant directory stream\n", __location__);
+ printf("(%s) creating a stream on a non-existant file\n", __location__);
io.generic.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.root_fid = 0;
io.ntcreatex.in.flags = 0;
io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
- io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.ntcreatex.in.create_options = 0;
io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
io.ntcreatex.in.share_access = 0;
io.ntcreatex.in.alloc_size = 0;
@@ -205,12 +284,6 @@ static bool test_stream_io(struct torture_context *tctx,
io.ntcreatex.in.security_flags = 0;
io.ntcreatex.in.fname = sname1;
status = smb_raw_open(cli->tree, mem_ctx, &io);
- CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
-
- printf("(%s) creating a stream on a non-existant file\n", __location__);
- io.ntcreatex.in.create_options = 0;
- io.ntcreatex.in.fname = sname1;
- status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.ntcreatex.out.file.fnum;
@@ -423,7 +496,7 @@ static bool test_stream_delete(struct torture_context *tctx,
sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One");
- printf("(%s) opening non-existant directory stream\n", __location__);
+ printf("(%s) opening non-existant file stream\n", __location__);
io.generic.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.root_fid = 0;
io.ntcreatex.in.flags = 0;
@@ -559,6 +632,8 @@ bool torture_raw_streams(struct torture_context *torture,
return false;
}
+ ret &= test_stream_dir(torture, cli, torture);
+ smb_raw_exit(cli->session);
ret &= test_stream_io(torture, cli, torture);
smb_raw_exit(cli->session);
ret &= test_stream_sharemodes(torture, cli, torture);
diff --git a/source4/torture/smb2/config.mk b/source4/torture/smb2/config.mk
index 11c4e1fa2c..9785303629 100644
--- a/source4/torture/smb2/config.mk
+++ b/source4/torture/smb2/config.mk
@@ -20,7 +20,9 @@ TORTURE_SMB2_OBJ_FILES = $(addprefix $(torturesrcdir)/smb2/, \
notify.o \
smb2.o \
persistent_handles.o \
- oplocks.o)
+ oplocks.o \
+ create.o \
+ read.o)
$(eval $(call proto_header_template,$(torturesrcdir)/smb2/proto.h,$(TORTURE_SMB2_OBJ_FILES:.o=.c)))
diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c
index 0004ea958e..826bb2d719 100644
--- a/source4/torture/smb2/connect.c
+++ b/source4/torture/smb2/connect.c
@@ -139,7 +139,7 @@ static NTSTATUS torture_smb2_write(struct torture_context *tctx, struct smb2_tre
/*
send a create
*/
-static struct smb2_handle torture_smb2_create(struct smb2_tree *tree,
+static struct smb2_handle torture_smb2_createfile(struct smb2_tree *tree,
const char *fname)
{
struct smb2_create io;
@@ -200,8 +200,8 @@ bool torture_smb2_connect(struct torture_context *torture)
return false;
}
- h1 = torture_smb2_create(tree, "test9.dat");
- h2 = torture_smb2_create(tree, "test9.dat");
+ h1 = torture_smb2_createfile(tree, "test9.dat");
+ h2 = torture_smb2_createfile(tree, "test9.dat");
status = torture_smb2_write(torture, tree, h1);
if (!NT_STATUS_IS_OK(status)) {
printf("Write failed - %s\n", nt_errstr(status));
diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c
new file mode 100644
index 0000000000..9c9e7e2997
--- /dev/null
+++ b/source4/torture/smb2/create.c
@@ -0,0 +1,201 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ SMB2 create test suite
+
+ Copyright (C) Andrew Tridgell 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 "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "torture/torture.h"
+#include "torture/smb2/proto.h"
+#include "param/param.h"
+#include "librpc/gen_ndr/ndr_security.h"
+
+#define FNAME "test_create.dat"
+
+#define CHECK_STATUS(status, correct) do { \
+ if (!NT_STATUS_EQUAL(status, correct)) { \
+ printf("(%s) Incorrect status %s - should be %s\n", \
+ __location__, nt_errstr(status), nt_errstr(correct)); \
+ return false; \
+ }} while (0)
+
+#define CHECK_EQUAL(v, correct) do { \
+ if (v != correct) { \
+ printf("(%s) Incorrect value for %s 0x%08x - should be 0x%08x\n", \
+ __location__, #v, v, correct); \
+ return false; \
+ }} while (0)
+
+/*
+ test some interesting combinations found by gentest
+ */
+bool torture_smb2_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
+{
+ struct smb2_create io;
+ NTSTATUS status;
+ TALLOC_CTX *tmp_ctx = talloc_new(tree);
+ uint32_t access_mask, file_attributes, denied_mask;
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ io.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ io.in.create_options = 0;
+ io.in.fname = FNAME;
+
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_util_close(tree, io.out.file.handle);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ io.in.create_options = 0xF0000000;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ io.in.create_options = 0x00100000;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED);
+
+ io.in.create_options = 0xF0100000;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED);
+
+ io.in.create_options = 0;
+
+ io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ io.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ io.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.in.desired_access = 0x08000000;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
+
+ io.in.desired_access = 0x04000000;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
+
+ io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ io.in.file_attributes = 0;
+ access_mask = 0;
+ {
+ int i;
+ for (i=0;i<32;i++) {
+ io.in.desired_access = 1<<i;
+ status = smb2_create(tree, tmp_ctx, &io);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ access_mask |= io.in.desired_access;
+ } else {
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb2_util_close(tree, io.out.file.handle);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ }
+ }
+ }
+
+ CHECK_EQUAL(access_mask, 0x0df0fe00);
+
+ io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = 0;
+ file_attributes = 0;
+ denied_mask = 0;
+ {
+ int i;
+ for (i=0;i<32;i++) {
+ io.in.file_attributes = 1<<i;
+ smb2_deltree(tree, FNAME);
+ status = smb2_create(tree, tmp_ctx, &io);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+ file_attributes |= io.in.file_attributes;
+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ denied_mask |= io.in.file_attributes;
+ } else {
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb2_util_close(tree, io.out.file.handle);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ }
+ }
+ }
+
+ CHECK_EQUAL(file_attributes, 0xffff8048);
+ CHECK_EQUAL(denied_mask, 0x4000);
+
+ smb2_deltree(tree, FNAME);
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = 0;
+ io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ io.in.share_access =
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ io.in.create_options = 0;
+ io.in.fname = FNAME ":stream1";
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ io.in.fname = FNAME;
+ io.in.file_attributes = 0x8040;
+ io.in.share_access =
+ NTCREATEX_SHARE_ACCESS_READ;
+ status = smb2_create(tree, tmp_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ talloc_free(tmp_ctx);
+
+ return true;
+}
+
+/*
+ basic testing of SMB2 create calls
+*/
+bool torture_smb2_create(struct torture_context *torture)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
+ struct smb2_tree *tree;
+ bool ret = true;
+
+ if (!torture_smb2_connection(torture, &tree)) {
+ return false;
+ }
+
+ ret &= torture_smb2_create_gentest(torture, tree);
+
+ smb2_deltree(tree, FNAME);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
diff --git a/source4/torture/smb2/getinfo.c b/source4/torture/smb2/getinfo.c
index c47a26277c..906d6e4f8d 100644
--- a/source4/torture/smb2/getinfo.c
+++ b/source4/torture/smb2/getinfo.c
@@ -51,9 +51,9 @@ static struct {
{ LEVEL(RAW_FILEINFO_COMPRESSION_INFORMATION) },
{ LEVEL(RAW_FILEINFO_NETWORK_OPEN_INFORMATION) },
{ LEVEL(RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION) },
-/*
-disabled until we know how the alignment now works
-{ LEVEL(RAW_FILEINFO_SMB2_ALL_EAS) }, */
+/*
+ { LEVEL(RAW_FILEINFO_SMB2_ALL_EAS) },
+*/
{ LEVEL(RAW_FILEINFO_SMB2_ALL_INFORMATION) },
{ LEVEL(RAW_FILEINFO_SEC_DESC) }
};
@@ -107,9 +107,6 @@ static bool torture_smb2_fileinfo(struct torture_context *tctx, struct smb2_tree
file_levels[i].dinfo.query_secdesc.in.secinfo_flags = 0x7;
}
if (file_levels[i].level == RAW_FILEINFO_SMB2_ALL_EAS) {
- if (torture_setting_bool(tctx, "samba4", false)) {
- continue;
- }
file_levels[i].finfo.all_eas.in.continue_flags =
SMB2_CONTINUE_FLAG_RESTART;
file_levels[i].dinfo.all_eas.in.continue_flags =
@@ -183,6 +180,9 @@ bool torture_smb2_getinfo(struct torture_context *torture)
return false;
}
+ smb2_deltree(tree, FNAME);
+ smb2_deltree(tree, DNAME);
+
status = torture_setup_complex_file(tree, FNAME);
if (!NT_STATUS_IS_OK(status)) {
return false;
diff --git a/source4/torture/smb2/lock.c b/source4/torture/smb2/lock.c
index e81647b497..4e21045a33 100644
--- a/source4/torture/smb2/lock.c
+++ b/source4/torture/smb2/lock.c
@@ -51,7 +51,7 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
struct smb2_handle h;
uint8_t buf[200];
struct smb2_lock lck;
- struct smb2_lock_element el[1];
+ struct smb2_lock_element el[2];
ZERO_STRUCT(buf);
@@ -90,7 +90,7 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
lck.in.file.handle.data[0] -=1;
lck.in.lock_count = 0x0001;
- lck.in.reserved = 0xFFFFFFFF;
+ lck.in.reserved = 0x123ab1;
lck.in.file.handle = h;
el[0].offset = UINT64_MAX;
el[0].length = UINT64_MAX;
@@ -100,16 +100,20 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VALUE(lck.out.reserved, 0);
+ lck.in.reserved = 0x123ab2;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
+ lck.in.reserved = 0x123ab3;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VALUE(lck.out.reserved, 0);
+ lck.in.reserved = 0x123ab4;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
+ lck.in.reserved = 0x123ab5;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VALUE(lck.out.reserved, 0);
@@ -162,27 +166,123 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
lck.in.file.handle = h;
el[0].offset = 0x00000000FFFFFFFF;
el[0].length = 0x00000000FFFFFFFF;
- el[0].reserved = 0x12345678;
+ el[0].reserved = 0x1234567;
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
status = smb2_lock(tree, &lck);
- CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ CHECK_STATUS(status, NT_STATUS_OK);
lck.in.lock_count = 0x0001;
- lck.in.reserved = 0x12345678;
+ lck.in.reserved = 0x1234567;
lck.in.file.handle = h;
el[0].offset = 0x00000000FFFFFFFF;
el[0].length = 0x00000000FFFFFFFF;
el[0].reserved = 0x00000000;
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0;
+ lck.in.file.handle = h;
+ el[0].offset = 1;
+ el[0].length = 1;
+ el[0].reserved = 0x00000000;
+ el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
+
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
+ lck.in.lock_count = 2;
+ lck.in.reserved = 0;
+ lck.in.file.handle = h;
+ el[0].offset = 9999;
+ el[0].length = 1;
+ el[0].reserved = 0x00000000;
+ el[1].offset = 9999;
+ el[1].length = 1;
+ el[1].reserved = 0x00000000;
+
+ lck.in.lock_count = 2;
+ el[0].flags = 0;
+ el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+ lck.in.lock_count = 2;
+ el[0].flags = 0;
+ el[1].flags = 0;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ lck.in.lock_count = 2;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
+ el[1].flags = 0;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ lck.in.lock_count = 1;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ lck.in.lock_count = 1;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ lck.in.lock_count = 1;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
+ lck.in.lock_count = 1;
+ el[0].flags = 0;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ lck.in.lock_count = 2;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
+ el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ lck.in.lock_count = 1;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
done:
return ret;
diff --git a/source4/torture/smb2/read.c b/source4/torture/smb2/read.c
new file mode 100644
index 0000000000..3e1d077b7d
--- /dev/null
+++ b/source4/torture/smb2/read.c
@@ -0,0 +1,141 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ SMB2 read test suite
+
+ Copyright (C) Andrew Tridgell 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 "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+
+#include "torture/torture.h"
+#include "torture/smb2/proto.h"
+
+#include "librpc/gen_ndr/ndr_security.h"
+
+#define CHECK_STATUS(status, correct) do { \
+ if (!NT_STATUS_EQUAL(status, correct)) { \
+ printf("(%s) Incorrect status %s - should be %s\n", \
+ __location__, nt_errstr(status), nt_errstr(correct)); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+#define CHECK_VALUE(v, correct) do { \
+ if ((v) != (correct)) { \
+ printf("(%s) Incorrect value %s=%d - should be %d\n", \
+ __location__, #v, v, correct); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+static bool test_read(struct torture_context *torture, struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_handle h;
+ uint8_t buf[70000];
+ struct smb2_read rd;
+ TALLOC_CTX *tmp_ctx = talloc_new(tree);
+
+ ZERO_STRUCT(buf);
+
+ status = torture_smb2_testfile(tree, "lock1.txt", &h);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ ZERO_STRUCT(rd);
+ rd.in.file.handle = h;
+ rd.in.length = 10;
+ rd.in.offset = 0;
+ rd.in.min_count = 1;
+
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VALUE(rd.out.data.length, 10);
+
+ rd.in.min_count = 0;
+ rd.in.length = 10;
+ rd.in.offset = sizeof(buf);
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+ rd.in.min_count = 0;
+ rd.in.length = 0;
+ rd.in.offset = sizeof(buf);
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VALUE(rd.out.data.length, 0);
+
+ rd.in.min_count = 1;
+ rd.in.length = 0;
+ rd.in.offset = sizeof(buf);
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+ rd.in.min_count = 0;
+ rd.in.length = 2;
+ rd.in.offset = sizeof(buf) - 1;
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VALUE(rd.out.data.length, 1);
+
+ rd.in.min_count = 2;
+ rd.in.length = 1;
+ rd.in.offset = sizeof(buf) - 1;
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+ rd.in.min_count = 0x10000;
+ rd.in.length = 1;
+ rd.in.offset = 0;
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+ rd.in.min_count = 0x10000 - 2;
+ rd.in.length = 1;
+ rd.in.offset = 0;
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+ rd.in.min_count = 10;
+ rd.in.length = 5;
+ rd.in.offset = 0;
+ status = smb2_read(tree, tmp_ctx, &rd);
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/* basic testing of SMB2 read
+*/
+struct torture_suite *torture_smb2_read_init(void)
+{
+ struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "READ");
+
+ torture_suite_add_1smb2_test(suite, "READ", test_read);
+
+ suite->description = talloc_strdup(suite, "SMB2-READ tests");
+
+ return suite;
+}
+
diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c
index 37eadcf7fd..f813148e1d 100644
--- a/source4/torture/smb2/smb2.c
+++ b/source4/torture/smb2/smb2.c
@@ -135,7 +135,9 @@ NTSTATUS torture_smb2_init(void)
torture_suite_add_simple_test(suite, "GETINFO", torture_smb2_getinfo);
torture_suite_add_simple_test(suite, "SETINFO", torture_smb2_setinfo);
torture_suite_add_simple_test(suite, "FIND", torture_smb2_find);
+ torture_suite_add_simple_test(suite, "CREATE", torture_smb2_create);
torture_suite_add_suite(suite, torture_smb2_lock_init());
+ torture_suite_add_suite(suite, torture_smb2_read_init());
torture_suite_add_simple_test(suite, "NOTIFY", torture_smb2_notify);
torture_suite_add_2smb2_test(suite, "PERSISTENT-HANDLES1", torture_smb2_persistent_handles1);
torture_suite_add_1smb2_test(suite, "OPLOCK-BATCH1", torture_smb2_oplock_batch1);
diff --git a/source4/torture/smbtorture.c b/source4/torture/smbtorture.c
index 418f933993..e1e84247b4 100644
--- a/source4/torture/smbtorture.c
+++ b/source4/torture/smbtorture.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
SMB torture tester
Copyright (C) Andrew Tridgell 1997-2003
- Copyright (C) Jelmer Vernooij 2006
+ Copyright (C) Jelmer Vernooij 2006-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
@@ -28,7 +28,7 @@
#include "libcli/libcli.h"
#include "lib/ldb/include/ldb.h"
#include "lib/events/events.h"
-#include "dynconfig.h"
+#include "dynconfig/dynconfig.h"
#include "torture/smbtorture.h"
#include "lib/util/dlinklist.h"
@@ -375,11 +375,24 @@ static void subunit_suite_start(struct torture_context *ctx,
{
}
+static void subunit_print_testname(struct torture_context *ctx,
+ struct torture_tcase *tcase,
+ struct torture_test *test)
+{
+ if (!strcmp(tcase->name, test->name)) {
+ printf("%s", test->name);
+ } else {
+ printf("%s.%s", tcase->name, test->name);
+ }
+}
+
static void subunit_test_start(struct torture_context *ctx,
struct torture_tcase *tcase,
struct torture_test *test)
{
- printf("test: %s\n", test->name);
+ printf("test: ");
+ subunit_print_testname(ctx, tcase, test);
+ printf("\n");
}
static void subunit_test_result(struct torture_context *context,
@@ -387,18 +400,20 @@ static void subunit_test_result(struct torture_context *context,
{
switch (res) {
case TORTURE_OK:
- printf("success: %s", context->active_test->name);
+ printf("success: ");
break;
case TORTURE_FAIL:
- printf("failure: %s", context->active_test->name);
+ printf("failure: ");
break;
case TORTURE_ERROR:
- printf("error: %s", context->active_test->name);
+ printf("error: ");
break;
case TORTURE_SKIP:
- printf("skip: %s", context->active_test->name);
+ printf("skip: ");
break;
}
+ subunit_print_testname(context, context->active_tcase, context->active_test);
+
if (reason)
printf(" [\n%s\n]", reason);
printf("\n");