From 8eef2e34128d713b741307a8c7b1650217698e06 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 29 May 2008 21:32:08 +1000 Subject: merged gentest.c and gentest_smb2.c The one gentest tool now covers both SMB and SMB2, using the command line switch --smb2 for SMB2 (This used to be commit d1125a303a31fbe08a9bd0064ec132b4d7cbb131) --- source4/torture/gentest.c | 2225 ++++++++++++++++++++++++++++++++------------- 1 file changed, 1575 insertions(+), 650 deletions(-) (limited to 'source4/torture/gentest.c') diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index 068b6bdc2f..fd6bd5cc0a 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -1,7 +1,9 @@ /* Unix SMB/CIFS implementation. - generic testing tool - Copyright (C) Andrew Tridgell 2003 + + generic testing tool - version with both SMB and SMB2 support + + Copyright (C) Andrew Tridgell 2003-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 @@ -25,12 +27,17 @@ #include "libcli/raw/request.h" #include "libcli/libcli.h" #include "libcli/raw/libcliraw.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" #include "librpc/gen_ndr/security.h" +#include "librpc/gen_ndr/ndr_security.h" #include "auth/credentials/credentials.h" #include "libcli/resolve/resolve.h" #include "auth/gensec/gensec.h" #include "param/param.h" #include "dynconfig/dynconfig.h" +#include "libcli/security/security.h" +#include "libcli/raw/raw_proto.h" #define NSERVERS 2 #define NINSTANCES 2 @@ -49,14 +56,20 @@ static struct gentest_options { const char *seeds_file; int use_preset_seeds; int fast_reconnect; + int mask_indexing; + int no_eas; + int no_acls; int skip_cleanup; + int valid; + int smb2; } options; /* mapping between open handles on the server and local handles */ static struct { bool active; uint_t instance; - uint_t server_fnum[NSERVERS]; + struct smb2_handle smb2_handle[NSERVERS]; /* SMB2 */ + uint16_t smb_handle[NSERVERS]; /* SMB */ const char *name; } *open_handles; static uint_t num_open_handles; @@ -64,7 +77,8 @@ static uint_t num_open_handles; /* state information for the servers. We open NINSTANCES connections to each server */ static struct { - struct smbcli_state *cli[NINSTANCES]; + struct smb2_tree *smb2_tree[NINSTANCES]; + struct smbcli_tree *smb_tree[NINSTANCES]; char *server_name; char *share_name; struct cli_credentials *credentials; @@ -80,7 +94,8 @@ static struct { /* oplock break info */ static struct { bool got_break; - uint16_t fnum; + struct smb2_handle smb2_handle; + uint16_t smb_handle; uint16_t handle; uint8_t level; bool do_close; @@ -100,14 +115,19 @@ static struct { NTSTATUS status; uint_t opnum; TALLOC_CTX *mem_ctx; + const char *mismatch; } current_op; +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 void idle_func(struct smbcli_transport *transport, void *private); +static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle, + uint8_t level, void *private_data); +static void idle_func_smb2(struct smb2_transport *transport, void *private); +static bool oplock_handler_smb(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private); +static void idle_func_smb(struct smbcli_transport *transport, void *private); /* check if a string should be ignored. This is used as the basis @@ -139,8 +159,15 @@ static bool connect_servers_fast(void) for (h=0;htree, - open_handles[h].server_fnum[i])))) { + NTSTATUS status; + if (options.smb2) { + status = smb2_util_close(servers[i].smb2_tree[open_handles[h].instance], + open_handles[h].smb2_handle[i]); + } else { + status = smbcli_close(servers[i].smb_tree[open_handles[h].instance], + open_handles[h].smb_handle[i]); + } + if (NT_STATUS_IS_ERR(status)) { return false; } open_handles[h].active = false; @@ -161,7 +188,7 @@ static bool connect_servers(struct event_context *ev, { int i, j; - if (options.fast_reconnect && servers[0].cli[0]) { + if (options.fast_reconnect && servers[0].smb2_tree[0]) { if (connect_servers_fast()) { return true; } @@ -170,17 +197,21 @@ static bool connect_servers(struct event_context *ev, /* close any existing connections */ for (i=0;itransport, oplock_handler, NULL); - smbcli_transport_idle_handler(servers[i].cli[j]->transport, idle_func, 50000, NULL); + if (options.smb2) { + servers[i].smb2_tree[j]->session->transport->oplock.handler = oplock_handler_smb2; + servers[i].smb2_tree[j]->session->transport->oplock.private_data = (void *)(uintptr_t)((i<<8)|j); + smb2_transport_idle_handler(servers[i].smb2_tree[j]->session->transport, + idle_func_smb2, 50000, NULL); + } else { + smbcli_oplock_handler(servers[i].smb_tree[j]->session->transport, oplock_handler_smb, + (void *)(uintptr_t)((i<<8)|j)); + smbcli_transport_idle_handler(servers[i].smb_tree[j]->session->transport, idle_func_smb, + 50000, (void *)(uintptr_t)((i<<8)|j)); + } } } @@ -218,33 +269,98 @@ static bool connect_servers(struct event_context *ev, static uint_t time_skew(void) { uint_t ret; - ret = labs(servers[0].cli[0]->transport->negotiate.server_time - - servers[1].cli[0]->transport->negotiate.server_time); + if (options.smb2) { + ret = labs(servers[0].smb2_tree[0]->session->transport->negotiate.system_time - + servers[1].smb2_tree[0]->session->transport->negotiate.system_time); + } else { + ret = labs(servers[0].smb_tree[0]->session->transport->negotiate.server_time - + servers[1].smb_tree[0]->session->transport->negotiate.server_time); + } return ret + 300; } + +static bool smb2_handle_equal(const struct smb2_handle *h1, const struct smb2_handle *h2) +{ + return memcmp(h1, h2, sizeof(struct smb2_handle)) == 0; +} + /* - turn an fnum for an instance into a handle + turn a server handle into a local handle */ -static uint_t fnum_to_handle(int server, int instance, uint16_t fnum) +static uint_t fnum_to_handle_smb2(int server, int instance, struct smb2_handle server_handle) { uint_t i; for (i=0;itree, - open_handles[h].server_fnum[i])))) { + NTSTATUS status; + status = smbcli_close(servers[i].smb_tree[open_handles[h].instance], + open_handles[h].smb_handle[i]); + if (NT_STATUS_IS_ERR(status)) { printf("INTERNAL ERROR: Close failed when recovering handle! - %s\n", - smbcli_errstr(servers[i].cli[open_handles[h].instance]->tree)); + nt_errstr(status)); } } printf("Recovered handle %d\n", h); num_open_handles--; } for (i=0;itransport; - - tid = SVAL(req->in.hdr, HDR_TID); - - notify.nttrans.level = RAW_NOTIFY_NTTRANS; - status = smb_raw_changenotify_recv(req, current_op.mem_ctx, ¬ify); - if (NT_STATUS_IS_OK(status)) { - printf("notify tid=%d num_changes=%d action=%d name=%s\n", - tid, - notify.nttrans.out.num_changes, - notify.nttrans.out.changes[0].action, - notify.nttrans.out.changes[0].name.s); + struct smb_ea_list eas; + int i; + if (options.no_eas) { + ZERO_STRUCT(eas); + return eas; } - - for (i=0;itransport && - tid == servers[i].cli[j]->tree->tid) { - notifies[i][j].notify_count++; - notifies[i][j].status = status; - notifies[i][j].notify = notify; - } - } + 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;itransport && - tid == servers[i].cli[j]->tree->tid) { + if (transport == servers[i].smb_tree[j]->session->transport && + tid == servers[i].smb_tree[j]->tid) { oplocks[i][j].got_break = true; - oplocks[i][j].fnum = fnum; - oplocks[i][j].handle = fnum_to_handle(i, j, fnum); + oplocks[i][j].smb_handle = fnum; + oplocks[i][j].handle = fnum_to_handle_smb(i, j, fnum); oplocks[i][j].level = level; oplocks[i][j].do_close = do_close; - tree = servers[i].cli[j]->tree; + tree = servers[i].smb_tree[j]; } } } @@ -784,7 +1012,7 @@ static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin return false; } - req->async.fn = oplock_handler_close_recv; + req->async.fn = oplock_handler_close_recv_smb; req->async.private = NULL; return true; @@ -796,83 +1024,212 @@ static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin an operation on another connection blocking until that break is acked we check for operations on all transports in the idle function */ -static void idle_func(struct smbcli_transport *transport, void *private) +static void idle_func_smb(struct smbcli_transport *transport, void *private) { int i, j; for (i=0;itransport) { - smbcli_transport_process(servers[i].cli[j]->transport); + if (servers[i].smb_tree[j] && + transport != servers[i].smb_tree[j]->session->transport) { + smbcli_transport_process(servers[i].smb_tree[j]->session->transport); } } } } - -/* - compare NTSTATUS, using checking ignored patterns -*/ -static bool compare_status(NTSTATUS status1, NTSTATUS status2) +static void oplock_handler_close_recv_smb2(struct smb2_request *req) { - if (NT_STATUS_EQUAL(status1, status2)) return true; + 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"); + } +} - /* one code being an error and the other OK is always an error */ - if (NT_STATUS_IS_OK(status1) || NT_STATUS_IS_OK(status2)) return false; +static void oplock_handler_ack_callback_smb2(struct smb2_request *req) +{ + NTSTATUS status; + struct smb2_break br; - /* if we are ignoring one of the status codes then consider this a match */ - if (ignore_pattern(nt_errstr(status1)) || - ignore_pattern(nt_errstr(status2))) { - return true; + 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"); } - return false; } - -/* - check for pending packets on all connections -*/ -static void check_pending(void) +static bool send_oplock_ack_smb2(struct smb2_tree *tree, struct smb2_handle handle, + uint8_t level) { - int i, j; + struct smb2_break br; + struct smb2_request *req; - msleep(20); + ZERO_STRUCT(br); + br.in.file.handle = handle; + br.in.oplock_level = level; + br.in.reserved = gen_reserved8(); + br.in.reserved2 = gen_reserved32(); - for (j=0;jtransport); - } - } + req = smb2_break_send(tree, &br); + if (req == NULL) return false; + req->async.fn = oplock_handler_ack_callback_smb2; + req->async.private_data = NULL; + return true; } /* - check that the same oplock breaks have been received by all instances + the oplock handler will either ack the break or close the file */ -static bool check_oplocks(const char *call) +static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle, + uint8_t level, void *private_data) { - int i, j; - int tries = 0; + struct smb2_close io; + unsigned i, j; + bool do_close; + struct smb2_tree *tree = NULL; + struct smb2_request *req; -again: - check_pending(); + srandom(current_op.seed); + do_close = gen_chance(50); - for (j=0;j> 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].smb2_handle = *handle; + oplocks[i][j].handle = fnum_to_handle_smb2(i, j, *handle); + oplocks[i][j].level = level; + oplocks[i][j].do_close = do_close; + tree = talloc_get_type(servers[i].smb2_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_smb2(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_smb2; + 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 +*/ +static void idle_func_smb2(struct smb2_transport *transport, void *private) +{ + int i, j; + for (i=0;isession->transport) { + // smb2_transport_process(servers[i].smb2_tree[j]->session->transport); + } + } + } + +} + + +/* + compare NTSTATUS, using checking ignored patterns +*/ +static bool compare_status(NTSTATUS status1, NTSTATUS status2) +{ + if (NT_STATUS_EQUAL(status1, status2)) return true; + + /* one code being an error and the other OK is always an error */ + if (NT_STATUS_IS_OK(status1) || NT_STATUS_IS_OK(status2)) { + current_op.mismatch = nt_errstr(status1); + return false; + } + + /* if we are ignoring one of the status codes then consider this a match */ + if (ignore_pattern(nt_errstr(status1)) || + ignore_pattern(nt_errstr(status2))) { + return true; + } + current_op.mismatch = nt_errstr(status1); + return false; +} + +/* + check for pending packets on all connections +*/ +static void check_pending(void) +{ + int i, j; + + msleep(20); + + for (j=0;jsession->transport); + } + } +} + +/* + check that the same oplock breaks have been received by all instances +*/ +static bool check_oplocks(const char *call) +{ + int i, j; + int tries = 0; + + if (!options.use_oplocks || options.smb2) { + /* no smb2 oplocks in gentest yet */ + return true; + } + +again: + check_pending(); + + for (j=0;jtree; \ + struct treetype *tree = servers[i].treefield[instance]; \ status[i] = call; \ } \ current_op.status = status[0]; \ @@ -984,43 +1350,92 @@ again: if (!compare_status(status[i], status[0])) { \ printf("status different in %s - %s %s\n", #call, \ nt_errstr(status[0]), nt_errstr(status[i])); \ + current_op.mismatch = nt_errstr(status[0]); \ return false; \ } \ } \ - if (!check_oplocks(#call)) return false; \ - if (!check_notifies(#call)) return false; \ + if (!check_oplocks(#call)) return false; \ + if (!check_notifies(#call)) return false; \ if (!NT_STATUS_IS_OK(status[0])) { \ return true; \ } \ } while(0) -#define ADD_HANDLE(name, field) do { \ - uint16_t fnums[NSERVERS]; \ +#define GEN_CALL_SMB(call) GEN_CALL(call, smbcli_tree, smb_tree) +#define GEN_CALL_SMB2(call) GEN_CALL(call, smb2_tree, smb2_tree) + +#define ADD_HANDLE_SMB2(name, field) do { \ + struct smb2_handle handles[NSERVERS]; \ + int i; \ + for (i=0;idacl, parm[1].field->dacl) && !ignore_pattern(#field)) { \ + current_op.mismatch = #field; \ + printf("Mismatch in %s\n", #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)) { \ + current_op.mismatch = #field; \ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \ (int)parm[0].field, (int)parm[1].field); \ return false; \ @@ -1029,10 +1444,12 @@ again: #define CHECK_WSTR_EQUAL(field) do { \ if ((!parm[0].field.s && parm[1].field.s) || (parm[0].field.s && !parm[1].field.s)) { \ + current_op.mismatch = #field; \ printf("%s is NULL!\n", #field); \ return false; \ } \ if (parm[0].field.s && strcmp(parm[0].field.s, parm[1].field.s) != 0 && !ignore_pattern(#field)) { \ + current_op.mismatch = #field; \ printf("Mismatch in %s - %s %s\n", #field, \ parm[0].field.s, parm[1].field.s); \ return false; \ @@ -1042,6 +1459,7 @@ again: #define CHECK_BLOB_EQUAL(field) do { \ if (memcmp(parm[0].field.data, parm[1].field.data, parm[0].field.length) != 0 && !ignore_pattern(#field)) { \ + current_op.mismatch = #field; \ printf("Mismatch in %s\n", #field); \ return false; \ } \ @@ -1051,6 +1469,7 @@ again: #define CHECK_TIMES_EQUAL(field) do { \ if (labs(parm[0].field - parm[1].field) > time_skew() && \ !ignore_pattern(#field)) { \ + current_op.mismatch = #field; \ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \ (int)parm[0].field, (int)parm[1].field); \ return false; \ @@ -1061,6 +1480,7 @@ again: if (labs(nt_time_to_unix(parm[0].field) - \ nt_time_to_unix(parm[1].field)) > time_skew() && \ !ignore_pattern(#field)) { \ + current_op.mismatch = #field; \ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \ (int)nt_time_to_unix(parm[0].field), \ (int)nt_time_to_unix(parm[1].field)); \ @@ -1068,89 +1488,305 @@ again: } \ } while(0) + /* - generate openx operations + compare returned fileinfo structures */ -static bool handler_openx(int instance) +static bool cmp_fileinfo(int instance, + union smb_fileinfo parm[NSERVERS], + NTSTATUS status[NSERVERS]) { - union smb_open parm[NSERVERS]; - NTSTATUS status[NSERVERS]; - - parm[0].openx.level = RAW_OPEN_OPENX; - parm[0].openx.in.flags = gen_openx_flags(); - parm[0].openx.in.open_mode = gen_openx_mode(); - parm[0].openx.in.search_attrs = gen_attrib(); - parm[0].openx.in.file_attrs = gen_attrib(); - parm[0].openx.in.write_time = gen_timet(); - parm[0].openx.in.open_func = gen_openx_func(); - parm[0].openx.in.size = gen_io_count(); - parm[0].openx.in.timeout = gen_timeout(); - parm[0].openx.in.fname = gen_fname_open(instance); + int i; + enum smb_fileinfo_level level = parm[0].generic.level; - if (!options.use_oplocks) { - /* mask out oplocks */ - parm[0].openx.in.flags &= ~(OPENX_FLAGS_REQUEST_OPLOCK| - OPENX_FLAGS_REQUEST_BATCH_OPLOCK); + if (level == RAW_FILEINFO_ALL_INFORMATION && + options.smb2) { + level = RAW_FILEINFO_SMB2_ALL_INFORMATION; } - - GEN_COPY_PARM; - GEN_CALL(smb_raw_open(tree, current_op.mem_ctx, &parm[i])); - - CHECK_EQUAL(openx.out.attrib); - CHECK_EQUAL(openx.out.size); - CHECK_EQUAL(openx.out.access); - CHECK_EQUAL(openx.out.ftype); - CHECK_EQUAL(openx.out.devstate); - CHECK_EQUAL(openx.out.action); - CHECK_EQUAL(openx.out.access_mask); - CHECK_EQUAL(openx.out.unknown); - CHECK_TIMES_EQUAL(openx.out.write_time); - /* open creates a new file handle */ - ADD_HANDLE(parm[0].openx.in.fname, openx.out.file.fnum); + switch (level) { + case RAW_FILEINFO_GENERIC: + return false; - return true; -} + case RAW_FILEINFO_GETATTR: + CHECK_ATTRIB(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_ATTRIB(getattre.out.attrib); + break; -/* - generate open operations -*/ -static bool handler_open(int instance) -{ - union smb_open parm[NSERVERS]; - NTSTATUS status[NSERVERS]; + 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_ATTRIB(standard.out.attrib); + break; - parm[0].openold.level = RAW_OPEN_OPEN; - parm[0].openold.in.open_mode = gen_bits_mask2(0xF, 0xFFFF); - parm[0].openold.in.search_attrs = gen_attrib(); - parm[0].openold.in.fname = gen_fname_open(instance); + 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_ATTRIB(ea_size.out.attrib); + CHECK_EQUAL(ea_size.out.ea_size); + break; - if (!options.use_oplocks) { - /* mask out oplocks */ - parm[0].openold.in.open_mode &= ~(OPENX_FLAGS_REQUEST_OPLOCK| - OPENX_FLAGS_REQUEST_BATCH_OPLOCK); - } - - GEN_COPY_PARM; - GEN_CALL(smb_raw_open(tree, current_op.mem_ctx, &parm[i])); + case RAW_FILEINFO_ALL_EAS: + CHECK_EQUAL(all_eas.out.num_eas); + for (i=0;igeneric.level = levels[i].level; -} - -/* - compare returned fileinfo structures -*/ -static bool cmp_fileinfo(int instance, - union smb_fileinfo parm[NSERVERS], - NTSTATUS status[NSERVERS]) -{ - int i; - - switch (parm[0].generic.level) { - case RAW_FILEINFO_GENERIC: - return false; - case RAW_FILEINFO_GETATTR: - CHECK_EQUAL(getattr.out.attrib); - CHECK_EQUAL(getattr.out.size); - CHECK_TIMES_EQUAL(getattr.out.write_time); + switch (info->generic.level) { + case RAW_SFILEINFO_SETATTR: + info->setattr.in.attrib = gen_attrib(); + info->setattr.in.write_time = gen_timet(); 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); + 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_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); + 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_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); + 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_FILEINFO_ALL_EAS: - CHECK_EQUAL(all_eas.out.num_eas); - for (i=0;ibasic_info.in.create_time = gen_nttime(); + info->basic_info.in.access_time = gen_nttime(); + info->basic_info.in.write_time = gen_nttime(); + info->basic_info.in.change_time = gen_nttime(); + info->basic_info.in.attrib = gen_attrib(); break; - - case RAW_FILEINFO_IS_NAME_VALID: + case RAW_SFILEINFO_DISPOSITION_INFO: + case RAW_SFILEINFO_DISPOSITION_INFORMATION: + info->disposition_info.in.delete_on_close = gen_bool(); break; - - case RAW_FILEINFO_BASIC_INFO: - 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); + 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; + case RAW_SFILEINFO_RENAME_INFORMATION: + case RAW_SFILEINFO_RENAME_INFORMATION_SMB2: + info->rename_information.in.overwrite = gen_bool(); + info->rename_information.in.root_fid = gen_root_fid(instance); + info->rename_information.in.new_name = gen_fname_open(instance); + break; + case RAW_SFILEINFO_POSITION_INFORMATION: + info->position_information.in.position = gen_offset(); + break; + case RAW_SFILEINFO_MODE_INFORMATION: + info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF); + 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_INFO2: + /* Untested */ break; + } +} +#endif - case RAW_FILEINFO_STANDARD_INFO: - case RAW_FILEINFO_STANDARD_INFORMATION: - CHECK_EQUAL(standard_info.out.alloc_size); - CHECK_EQUAL(standard_info.out.size); - CHECK_EQUAL(standard_info.out.nlink); - CHECK_EQUAL(standard_info.out.delete_pending); - CHECK_EQUAL(standard_info.out.directory); +/* + generate a fileinfo query structure +*/ +static void gen_setfileinfo(int instance, union smb_setfileinfo *info) +{ + int i; + #undef LVL + #define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v} + struct levels { + enum smb_setfileinfo_level level; + const char *name; + }; + struct levels smb_levels[] = { + LVL(EA_SET), LVL(BASIC_INFO), LVL(DISPOSITION_INFO), + LVL(STANDARD), LVL(ALLOCATION_INFO), LVL(END_OF_FILE_INFO), + LVL(SETATTR), LVL(SETATTRE), LVL(BASIC_INFORMATION), + LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION), + LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION), + LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION), + LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040), + }; + struct levels smb2_levels[] = { + LVL(BASIC_INFORMATION), + LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION), + LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION), + LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION), + LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040) + }; + struct levels *levels = options.smb2?smb2_levels:smb_levels; + uint32_t num_levels = options.smb2?ARRAY_SIZE(smb2_levels):ARRAY_SIZE(smb_levels); + + do { + i = gen_int_range(0, num_levels-1); + } while (ignore_pattern(levels[i].name)); + + info->generic.level = levels[i].level; + + 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_BASIC_INFO: + case RAW_SFILEINFO_BASIC_INFORMATION: + info->basic_info.in.create_time = gen_nttime(); + info->basic_info.in.access_time = gen_nttime(); + info->basic_info.in.write_time = gen_nttime(); + 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; + case RAW_SFILEINFO_RENAME_INFORMATION: + case RAW_SFILEINFO_RENAME_INFORMATION_SMB2: + info->rename_information.in.overwrite = gen_bool(); + info->rename_information.in.root_fid = gen_root_fid(instance); + info->rename_information.in.new_name = gen_fname_open(instance); + break; + case RAW_SFILEINFO_POSITION_INFORMATION: + info->position_information.in.position = gen_offset(); + break; + case RAW_SFILEINFO_MODE_INFORMATION: + info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF); break; - case RAW_FILEINFO_EA_INFO: - case RAW_FILEINFO_EA_INFORMATION: - CHECK_EQUAL(ea_info.out.ea_size); + case RAW_SFILEINFO_GENERIC: + case RAW_SFILEINFO_SEC_DESC: + 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; + } +} + + + +/* + generate a fileinfo query structure +*/ +static void gen_fileinfo_smb(int instance, union smb_fileinfo *info) +{ + int i; + #undef LVL + #define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v} + struct { + 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(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(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION), + LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION) + }; + do { + i = gen_int_range(0, ARRAY_SIZE(levels)-1); + } while (ignore_pattern(levels[i].name)); + + info->generic.level = levels[i].level; +} + +/* + generate qpathinfo operations +*/ +static bool handler_smb_qpathinfo(int instance) +{ + union smb_fileinfo parm[NSERVERS]; + NTSTATUS status[NSERVERS]; + + parm[0].generic.in.file.path = gen_fname_open(instance); + + gen_fileinfo_smb(instance, &parm[0]); + + GEN_COPY_PARM; + GEN_CALL_SMB(smb_raw_pathinfo(tree, current_op.mem_ctx, &parm[i])); + + return cmp_fileinfo(instance, parm, status); +} + +/* + generate qfileinfo operations +*/ +static bool handler_smb_qfileinfo(int instance) +{ + union smb_fileinfo parm[NSERVERS]; + NTSTATUS status[NSERVERS]; + + parm[0].generic.in.file.fnum = gen_fnum(instance); + + gen_fileinfo_smb(instance, &parm[0]); + + GEN_COPY_PARM; + GEN_SET_FNUM_SMB(generic.in.file.fnum); + GEN_CALL_SMB(smb_raw_fileinfo(tree, current_op.mem_ctx, &parm[i])); + + return cmp_fileinfo(instance, parm, status); +} + + +/* + generate setpathinfo operations +*/ +static bool handler_smb_spathinfo(int instance) +{ + union smb_setfileinfo parm[NSERVERS]; + NTSTATUS status[NSERVERS]; + + parm[0].generic.in.file.path = gen_fname_open(instance); + + gen_setfileinfo(instance, &parm[0]); + + GEN_COPY_PARM; + + /* a special case for the fid in a RENAME */ + if (parm[0].generic.level == RAW_SFILEINFO_RENAME_INFORMATION && + parm[0].rename_information.in.root_fid != 0) { + GEN_SET_FNUM_SMB(rename_information.in.root_fid); + } + + GEN_CALL_SMB(smb_raw_setpathinfo(tree, &parm[i])); + + return true; +} + + +/* + generate setfileinfo operations +*/ +static bool handler_smb_sfileinfo(int instance) +{ + union smb_setfileinfo parm[NSERVERS]; + NTSTATUS status[NSERVERS]; + + parm[0].generic.in.file.fnum = gen_fnum(instance); + + gen_setfileinfo(instance, &parm[0]); + + GEN_COPY_PARM; + GEN_SET_FNUM_SMB(generic.in.file.fnum); + GEN_CALL_SMB(smb_raw_setfileinfo(tree, &parm[i])); + + return true; +} + + +/* + this is called when a change notify reply comes in +*/ +static void async_notify_smb(struct smbcli_request *req) +{ + union smb_notify notify; + NTSTATUS status; + int i, j; + uint16_t tid; + struct smbcli_transport *transport = req->transport; + + tid = SVAL(req->in.hdr, HDR_TID); + + notify.nttrans.level = RAW_NOTIFY_NTTRANS; + status = smb_raw_changenotify_recv(req, current_op.mem_ctx, ¬ify); + if (NT_STATUS_IS_OK(status) && notify.nttrans.out.num_changes > 0) { + printf("notify tid=%d num_changes=%d action=%d name=%s\n", + tid, + notify.nttrans.out.num_changes, + notify.nttrans.out.changes[0].action, + notify.nttrans.out.changes[0].name.s); + } + + for (i=0;isession->transport && + tid == servers[i].smb_tree[j]->tid) { + notifies[i][j].notify_count++; + notifies[i][j].status = status; + notifies[i][j].notify = notify; + } + } + } +} + +/* + generate change notify operations +*/ +static bool handler_smb_notify(int instance) +{ + union smb_notify parm[NSERVERS]; + int n; + + ZERO_STRUCT(parm[0]); + parm[0].nttrans.level = RAW_NOTIFY_NTTRANS; + parm[0].nttrans.in.buffer_size = gen_io_count(); + parm[0].nttrans.in.completion_filter = gen_bits_mask(0xFF); + parm[0].nttrans.in.file.fnum = gen_fnum(instance); + parm[0].nttrans.in.recursive = gen_bool(); + + GEN_COPY_PARM; + GEN_SET_FNUM_SMB(nttrans.in.file.fnum); + + for (n=0;nasync.fn = async_notify_smb; + } + + return true; +} + + +/* + generate ntcreatex operations +*/ +static bool handler_smb2_create(int instance) +{ + struct smb2_create parm[NSERVERS]; + NTSTATUS status[NSERVERS]; + + ZERO_STRUCT(parm[0]); + parm[0].in.security_flags = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFF); + parm[0].in.oplock_level = gen_bits_levels(3, 90, 0x0, 70, 0x9, 100, 0xFF); + parm[0].in.impersonation_level = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFFFFFFFF); + parm[0].in.create_flags = gen_reserved64(); + 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(); + parm[0].in.alloc_size = gen_alloc_size(); + parm[0].in.durable_open = gen_bool(); + parm[0].in.query_maximal_access = gen_bool(); + parm[0].in.timewarp = gen_timewarp(); + parm[0].in.query_on_disk_id = gen_bool(); + parm[0].in.sec_desc = gen_sec_desc(); + + if (!options.use_oplocks) { + /* mask out oplocks */ + parm[0].in.oplock_level = 0; + } + + if (options.valid) { + parm[0].in.security_flags &= 3; + parm[0].in.oplock_level &= 9; + parm[0].in.impersonation_level &= 3; + } + + GEN_COPY_PARM; + GEN_CALL_SMB2(smb2_create(tree, current_op.mem_ctx, &parm[i])); + + CHECK_EQUAL(out.oplock_level); + CHECK_EQUAL(out.reserved); + CHECK_EQUAL(out.create_action); + CHECK_NTTIMES_EQUAL(out.create_time); + CHECK_NTTIMES_EQUAL(out.access_time); + CHECK_NTTIMES_EQUAL(out.write_time); + CHECK_NTTIMES_EQUAL(out.change_time); + CHECK_EQUAL(out.alloc_size); + CHECK_EQUAL(out.size); + CHECK_ATTRIB(out.file_attr); + CHECK_EQUAL(out.reserved2); + CHECK_EQUAL(out.maximal_access); + + /* ntcreatex creates a new file handle */ + ADD_HANDLE_SMB2(parm[0].in.fname, out.file.handle); + + return true; +} + +/* + generate close operations +*/ +static bool handler_smb2_close(int instance) +{ + struct smb2_close parm[NSERVERS]; + NTSTATUS status[NSERVERS]; - case RAW_FILEINFO_NAME_INFO: - case RAW_FILEINFO_NAME_INFORMATION: - CHECK_WSTR_EQUAL(name_info.out.fname); - break; + ZERO_STRUCT(parm[0]); + parm[0].in.file.handle.data[0] = gen_fnum_close(instance); + parm[0].in.flags = gen_bits_mask2(0x1, 0xFFFF); - 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; + GEN_COPY_PARM; + GEN_SET_FNUM_SMB2(in.file.handle); + GEN_CALL_SMB2(smb2_close(tree, &parm[i])); - case RAW_FILEINFO_ALT_NAME_INFO: - case RAW_FILEINFO_ALT_NAME_INFORMATION: - CHECK_WSTR_EQUAL(alt_name_info.out.fname); - break; + CHECK_EQUAL(out.flags); + CHECK_EQUAL(out._pad); + CHECK_NTTIMES_EQUAL(out.create_time); + CHECK_NTTIMES_EQUAL(out.access_time); + CHECK_NTTIMES_EQUAL(out.write_time); + CHECK_NTTIMES_EQUAL(out.change_time); + CHECK_EQUAL(out.alloc_size); + CHECK_EQUAL(out.size); + CHECK_ATTRIB(out.file_attr); - case RAW_FILEINFO_STREAM_INFO: - case RAW_FILEINFO_STREAM_INFORMATION: - CHECK_EQUAL(stream_info.out.num_streams); - for (i=0;isession->transport)); + + return true; +} + + /* generate a fileinfo query structure */ -static void gen_setfileinfo(int instance, union smb_setfileinfo *info) +static void gen_fileinfo_smb2(int instance, union smb_fileinfo *info) { int i; - #undef LVL - #define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v} + #define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v} struct { - enum smb_setfileinfo_level level; + enum smb_fileinfo_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(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION), - LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION), - LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION), - LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040) + 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(SMB2_ALL_INFORMATION), + LVL(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION), + LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION), + LVL(SMB2_ALL_EAS), LVL(SMB2_ALL_INFORMATION), LVL(SEC_DESC), }; do { i = gen_int_range(0, ARRAY_SIZE(levels)-1); } while (ignore_pattern(levels[i].name)); info->generic.level = levels[i].level; - - 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_BASIC_INFO: - case RAW_SFILEINFO_BASIC_INFORMATION: - info->basic_info.in.create_time = gen_nttime(); - info->basic_info.in.access_time = gen_nttime(); - info->basic_info.in.write_time = gen_nttime(); - 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; - case RAW_SFILEINFO_RENAME_INFORMATION: - case RAW_SFILEINFO_RENAME_INFORMATION_SMB2: - info->rename_information.in.overwrite = gen_bool(); - info->rename_information.in.root_fid = gen_root_fid(instance); - info->rename_information.in.new_name = gen_fname_open(instance); - break; - case RAW_SFILEINFO_POSITION_INFORMATION: - info->position_information.in.position = gen_offset(); - break; - case RAW_SFILEINFO_MODE_INFORMATION: - info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF); - 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_INFO2: - /* Untested */ - break; - } } /* - generate setpathinfo operations + generate qfileinfo operations */ -static bool handler_spathinfo(int instance) +static bool handler_smb2_qfileinfo(int instance) { - union smb_setfileinfo parm[NSERVERS]; + union smb_fileinfo parm[NSERVERS]; NTSTATUS status[NSERVERS]; - parm[0].generic.in.file.path = gen_fname_open(instance); + parm[0].generic.in.file.handle.data[0] = gen_fnum(instance); - gen_setfileinfo(instance, &parm[0]); + gen_fileinfo_smb2(instance, &parm[0]); GEN_COPY_PARM; + GEN_SET_FNUM_SMB2(generic.in.file.handle); + GEN_CALL_SMB2(smb2_getinfo_file(tree, current_op.mem_ctx, &parm[i])); - /* a special case for the fid in a RENAME */ - if (parm[0].generic.level == RAW_SFILEINFO_RENAME_INFORMATION && - parm[0].rename_information.in.root_fid != 0) { - GEN_SET_FNUM(rename_information.in.root_fid); - } - - GEN_CALL(smb_raw_setpathinfo(tree, &parm[i])); - - return true; + return cmp_fileinfo(instance, parm, status); } /* generate setfileinfo operations */ -static bool handler_sfileinfo(int instance) +static bool handler_smb2_sfileinfo(int instance) { union smb_setfileinfo parm[NSERVERS]; NTSTATUS status[NSERVERS]; @@ -1826,36 +2744,8 @@ 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])); - - return true; -} - - -/* - generate change notify operations -*/ -static bool handler_notify(int instance) -{ - union smb_notify parm[NSERVERS]; - int n; - - ZERO_STRUCT(parm[0]); - parm[0].nttrans.level = RAW_NOTIFY_NTTRANS; - parm[0].nttrans.in.buffer_size = gen_io_count(); - parm[0].nttrans.in.completion_filter = gen_bits_mask(0xFF); - parm[0].nttrans.in.file.fnum = gen_fnum(instance); - parm[0].nttrans.in.recursive = gen_bool(); - - GEN_COPY_PARM; - GEN_SET_FNUM(nttrans.in.file.fnum); - - for (n=0;ntree, &parm[n]); - req->async.fn = async_notify; - } + GEN_SET_FNUM_SMB2(generic.in.file.handle); + GEN_CALL_SMB2(smb2_setinfo_file(tree, &parm[i])); return true; } @@ -1866,20 +2756,30 @@ static bool handler_notify(int instance) static void wipe_files(void) { int i; + NTSTATUS status; if (options.skip_cleanup) { return; } for (i=0;itree, "\\gentest"); + int n; + if (options.smb2) { + n = smb2_deltree(servers[i].smb2_tree[0], "gentest"); + } else { + n = smbcli_deltree(servers[i].smb_tree[0], "gentest"); + } if (n == -1) { printf("Failed to wipe tree on server %d\n", i); exit(1); } - if (NT_STATUS_IS_ERR(smbcli_mkdir(servers[i].cli[0]->tree, "\\gentest"))) { - printf("Failed to create \\gentest - %s\n", - smbcli_errstr(servers[i].cli[0]->tree)); + if (options.smb2) { + status = smb2_util_mkdir(servers[i].smb2_tree[0], "gentest"); + } else { + status = smbcli_mkdir(servers[i].smb_tree[0], "gentest"); + } + if (NT_STATUS_IS_ERR(status)) { + printf("Failed to create gentest on server %d - %s\n", i, nt_errstr(status)); exit(1); } if (n > 0) { @@ -1917,27 +2817,39 @@ static void dump_seeds(void) static struct { const char *name; bool (*handler)(int instance); + bool smb2; int count, success_count; } gen_ops[] = { - {"OPEN", handler_open}, - {"OPENX", handler_openx}, - {"NTCREATEX", handler_ntcreatex}, - {"CLOSE", handler_close}, - {"UNLINK", handler_unlink}, - {"MKDIR", handler_mkdir}, - {"RMDIR", handler_rmdir}, - {"RENAME", handler_rename}, - {"NTRENAME", handler_ntrename}, - {"READX", handler_readx}, - {"WRITEX", handler_writex}, - {"CHKPATH", handler_chkpath}, - {"LOCKINGX", handler_lockingx}, - {"QPATHINFO", handler_qpathinfo}, - {"QFILEINFO", handler_qfileinfo}, - {"SPATHINFO", handler_spathinfo}, - {"SFILEINFO", handler_sfileinfo}, - {"NOTIFY", handler_notify}, - {"SEEK", handler_seek}, + {"CREATE", handler_smb2_create, true}, + {"CLOSE", handler_smb2_close, true}, + {"READ", handler_smb2_read, true}, + {"WRITE", handler_smb2_write, true}, + {"LOCK", handler_smb2_lock, true}, + {"FLUSH", handler_smb2_flush, true}, + {"ECHO", handler_smb2_echo, true}, + {"QFILEINFO", handler_smb2_qfileinfo, true}, + {"SFILEINFO", handler_smb2_sfileinfo, true}, + + {"OPEN", handler_smb_open, false}, + {"OPENX", handler_smb_openx, false}, + {"NTCREATEX", handler_smb_ntcreatex, false}, + {"CLOSE", handler_smb_close, false}, + {"UNLINK", handler_smb_unlink, false}, + {"MKDIR", handler_smb_mkdir, false}, + {"RMDIR", handler_smb_rmdir, false}, + {"RENAME", handler_smb_rename, false}, + {"NTRENAME", handler_smb_ntrename, false}, + {"READX", handler_smb_readx, false}, + {"WRITEX", handler_smb_writex, false}, + {"CHKPATH", handler_smb_chkpath, false}, + {"SEEK", handler_smb_seek, false}, + {"LOCKINGX", handler_smb_lockingx, false}, + {"QPATHINFO", handler_smb_qpathinfo, false}, + {"QFILEINFO", handler_smb_qfileinfo, false}, + {"SPATHINFO", handler_smb_spathinfo, false}, + {"SFILEINFO", handler_smb_sfileinfo, false}, + {"NOTIFY", handler_smb_notify, false}, + {"SEEK", handler_smb_seek, false}, }; @@ -1981,7 +2893,8 @@ static int run_test(struct event_context *ev, struct loadparm_context *lp_ctx) /* generate a non-ignored operation */ do { which_op = gen_int_range(0, ARRAY_SIZE(gen_ops)-1); - } while (ignore_pattern(gen_ops[which_op].name)); + } while (ignore_pattern(gen_ops[which_op].name) || + gen_ops[which_op].smb2 != options.smb2); DEBUG(3,("Generating op %s on instance %d\n", gen_ops[which_op].name, instance)); @@ -2030,6 +2943,7 @@ static void backtrack_analyze(struct event_context *ev, struct loadparm_context *lp_ctx) { int chunk, ret; + const char *mismatch = current_op.mismatch; chunk = options.numops / 2; @@ -2056,6 +2970,10 @@ static void backtrack_analyze(struct event_context *ev, if (ret == options.numops) { /* this chunk is needed */ base += chunk; + } else if (mismatch != current_op.mismatch && + strcmp(mismatch, current_op.mismatch)) { + base += chunk; + printf("Different error in backtracking\n"); } else if (ret < base) { printf("damn - inconsistent errors! found early error\n"); options.numops = ret+1; @@ -2189,6 +3107,7 @@ static bool split_unc_name(const char *unc, char **server, char **share) enum {OPT_UNCLIST=1000}; struct poptOption long_options[] = { POPT_AUTOHELP + {"smb2", 0, POPT_ARG_NONE, &options.smb2, 0, "use SMB2 protocol", NULL}, {"seed", 0, POPT_ARG_INT, &options.seed, 0, "Seed to use for randomizer", NULL}, {"num-ops", 0, POPT_ARG_INT, &options.numops, 0, "num ops", NULL}, {"oplocks", 0, POPT_ARG_NONE, &options.use_oplocks,0, "use oplocks", NULL}, @@ -2202,7 +3121,11 @@ 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}, + {"noacls", 0, POPT_ARG_NONE, &options.no_acls, 0, "don't use ACLs", NULL}, {"skip-cleanup", 0, POPT_ARG_NONE, &options.skip_cleanup, 0, "don't delete files at start", NULL}, + {"valid", 0, POPT_ARG_NONE, &options.valid, 0, "generate only valid fields", NULL}, POPT_COMMON_SAMBA POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS @@ -2210,6 +3133,8 @@ static bool split_unc_name(const char *unc, char **server, char **share) { NULL } }; + memset(&bad_smb2_handle, 0xFF, sizeof(bad_smb2_handle)); + setlinebuf(stdout); options.seed = time(NULL); options.numops = 1000; -- cgit From beaa01e403dda7557a6acdf0181d79d58a33bbbe Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 30 May 2008 17:03:54 +1000 Subject: implemented client side SMB2 signing This doessn't work against Windows yet, and I've submitted a WSPP request for clarification of the docs to try and find out why. Meanwhile this is no worse than what we had, as it only gets used when the server demands signing, and we didn't work then anyway. (This used to be commit b788096add3586d7277efcd3bf5ca7f3a604cb7a) --- source4/torture/gentest.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/torture/gentest.c') diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index fd6bd5cc0a..07d394fad6 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -213,6 +213,9 @@ static bool connect_servers(struct event_context *ev, for (i=0;iusername, j); @@ -226,10 +229,8 @@ static bool connect_servers(struct event_context *ev, lp_resolve_context(lp_ctx), servers[i].credentials, &servers[i].smb2_tree[j], - ev); + ev, &smb_options); } else { - struct smbcli_options smb_options; - lp_smbcli_options(lp_ctx, &smb_options); status = smbcli_tree_full_connection(NULL, &servers[i].smb_tree[j], servers[i].server_name, -- cgit