From b51703baf152c309ce325ce573c1683d7e503122 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 15 Nov 2005 04:38:59 +0000 Subject: r11730: added parsing and tests for a bunch more SMB2 getinfo levels (This used to be commit ca65bf0235cbfab451e5d5ceac9f714acc0cd46c) --- source4/torture/smb2/config.mk | 4 +- source4/torture/smb2/connect.c | 23 +++-- source4/torture/smb2/getinfo.c | 116 ++++++++++++++++++++++++ source4/torture/smb2/scan.c | 64 ++++++------- source4/torture/smb2/util.c | 199 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 359 insertions(+), 47 deletions(-) create mode 100644 source4/torture/smb2/getinfo.c create mode 100644 source4/torture/smb2/util.c (limited to 'source4/torture/smb2') diff --git a/source4/torture/smb2/config.mk b/source4/torture/smb2/config.mk index 2c6dfd4fc9..7c7cdeab62 100644 --- a/source4/torture/smb2/config.mk +++ b/source4/torture/smb2/config.mk @@ -4,7 +4,9 @@ [SUBSYSTEM::TORTURE_SMB2] ADD_OBJ_FILES = \ connect.o \ - scan.o + scan.o \ + util.o \ + getinfo.o REQUIRED_SUBSYSTEMS = \ LIBCLI_SMB2 # End SUBSYSTEM TORTURE_SMB2 diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c index 4907aadecb..077c873d08 100644 --- a/source4/torture/smb2/connect.c +++ b/source4/torture/smb2/connect.c @@ -82,12 +82,26 @@ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle ha w.in.handle = handle; w.in.data = data; + memset(w.in._pad, 0xff, 16); + + status = smb2_write(tree, &w); + if (!NT_STATUS_IS_OK(status)) { + printf("write failed - %s\n", nt_errstr(status)); + return status; + } + + torture_smb2_all_info(tree, handle); + + memset(w.in._pad, 0xff, 16); + status = smb2_write(tree, &w); if (!NT_STATUS_IS_OK(status)) { printf("write failed - %s\n", nt_errstr(status)); return status; } + torture_smb2_all_info(tree, handle); + ZERO_STRUCT(r); r.in.buffer_code = 0x31; r.in.length = data.length; @@ -168,16 +182,9 @@ BOOL torture_smb2_connect(void) { TALLOC_CTX *mem_ctx = talloc_new(NULL); struct smb2_tree *tree; - const char *host = lp_parm_string(-1, "torture", "host"); - const char *share = lp_parm_string(-1, "torture", "share"); - struct cli_credentials *credentials = cmdline_credentials; struct smb2_handle h1, h2; - NTSTATUS status; - status = smb2_connect(mem_ctx, host, share, credentials, &tree, - event_context_find(mem_ctx)); - if (!NT_STATUS_IS_OK(status)) { - printf("Connection failed - %s\n", nt_errstr(status)); + if (!torture_smb2_connection(mem_ctx, &tree)) { return False; } diff --git a/source4/torture/smb2/getinfo.c b/source4/torture/smb2/getinfo.c new file mode 100644 index 0000000000..843ef5b5d0 --- /dev/null +++ b/source4/torture/smb2/getinfo.c @@ -0,0 +1,116 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 getinfo test suite + + Copyright (C) Andrew Tridgell 2005 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" + +static struct { + const char *name; + uint16_t level; + NTSTATUS fstatus; + NTSTATUS dstatus; + union smb2_fileinfo finfo; + union smb2_fileinfo dinfo; +} levels[] = { +#define LEVEL(x) #x, x + { LEVEL(SMB2_GETINFO_FS_01) }, + { LEVEL(SMB2_GETINFO_FS_03) }, + { LEVEL(SMB2_GETINFO_FS_04) }, + { LEVEL(SMB2_GETINFO_FS_ATTRIB_INFO) }, + { LEVEL(SMB2_GETINFO_FS_06) }, + { LEVEL(SMB2_GETINFO_FS_07) }, + { LEVEL(SMB2_GETINFO_FS_08) }, + { LEVEL(SMB2_GETINFO_SECURITY) }, + { LEVEL(SMB2_GETINFO_FILE_BASIC_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_SIZE_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_ID) }, + { LEVEL(SMB2_GETINFO_FILE_EA_SIZE) }, + { LEVEL(SMB2_GETINFO_FILE_ACCESS_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_0E) }, + { LEVEL(SMB2_GETINFO_FILE_ALL_EAS) }, + { LEVEL(SMB2_GETINFO_FILE_10) }, + { LEVEL(SMB2_GETINFO_FILE_11) }, + { LEVEL(SMB2_GETINFO_FILE_ALL_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_SHORT_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_STREAM_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_EOF_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_STANDARD_INFO) }, + { LEVEL(SMB2_GETINFO_FILE_ATTRIB_INFO) } +}; + +#define FNAME "testsmb2_file.dat" +#define DNAME "testsmb2_dir" + +/* basic testing of all SMB2 getinfo levels +*/ +BOOL torture_smb2_getinfo(void) +{ + TALLOC_CTX *mem_ctx = talloc_new(NULL); + struct smb2_handle hfile, hdir; + struct smb2_tree *tree; + NTSTATUS status; + int i; + + if (!torture_smb2_connection(mem_ctx, &tree)) { + goto failed; + } + + torture_setup_complex_file(FNAME); + torture_setup_complex_file(FNAME ":streamtwo"); + torture_setup_complex_dir(DNAME); + torture_setup_complex_file(DNAME ":streamtwo"); + + status = torture_smb2_testfile(tree, FNAME, &hfile); + if (!NT_STATUS_IS_OK(status)) { + printf("Unable to create test file '%s' - %s\n", FNAME, nt_errstr(status)); + goto failed; + } + + status = torture_smb2_testdir(tree, DNAME, &hdir); + if (!NT_STATUS_IS_OK(status)) { + printf("Unable to create test directory '%s' - %s\n", DNAME, nt_errstr(status)); + goto failed; + } + + torture_smb2_all_info(tree, hfile); + torture_smb2_all_info(tree, hdir); + + for (i=0;itree, fname); - } - - talloc_free(cli); - return fnum != -1; -} - - - /* scan for valid SMB2 getinfo levels */ @@ -60,9 +35,6 @@ BOOL torture_smb2_getinfo_scan(void) { TALLOC_CTX *mem_ctx = talloc_new(NULL); struct smb2_tree *tree; - const char *host = lp_parm_string(-1, "torture", "host"); - const char *share = lp_parm_string(-1, "torture", "share"); - struct cli_credentials *credentials = cmdline_credentials; NTSTATUS status; struct smb2_getinfo io; struct smb2_create cr; @@ -70,14 +42,11 @@ BOOL torture_smb2_getinfo_scan(void) int c, i; const char *fname = "scan-getinfo.dat"; - status = smb2_connect(mem_ctx, host, share, credentials, &tree, - event_context_find(mem_ctx)); - if (!NT_STATUS_IS_OK(status)) { - printf("Connection failed - %s\n", nt_errstr(status)); + if (!torture_smb2_connection(mem_ctx, &tree)) { return False; } - if (!setup_complex_file(fname)) { + if (!torture_setup_complex_file(fname)) { printf("Failed to setup complex file '%s'\n", fname); } @@ -108,6 +77,27 @@ BOOL torture_smb2_getinfo_scan(void) io.in.max_response_size = 0xFFFF; io.in.handle = handle; + io.in.max_response_size = 128; + io.in.unknown1 = 0; + io.in.level = SMB2_GETINFO_FILE_ALL_INFO; + status = smb2_getinfo(tree, mem_ctx, &io); + + io.in.max_response_size = 128; + io.in.unknown1 = 64; + io.in.flags = 64; + io.in.unknown3 = 64; + io.in.unknown4 = 64; + io.in.level = SMB2_GETINFO_FILE_ALL_INFO; + status = smb2_getinfo(tree, mem_ctx, &io); + + if (!NT_STATUS_IS_OK(status)) { + printf("level 0x%04x is %d bytes - %s\n", + io.in.level, io.out.blob.length, nt_errstr(status)); + dump_data(1, io.out.blob.data, io.out.blob.length); + } + + return True; + for (c=0;c<5;c++) { for (i=0;i<0x100;i++) { io.in.level = (i<<8) | c; @@ -117,11 +107,9 @@ BOOL torture_smb2_getinfo_scan(void) NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { continue; } - if (NT_STATUS_IS_OK(status)) { - printf("level 0x%04x is %d bytes\n", - io.in.level, io.out.blob.length); - dump_data(1, io.out.blob.data, io.out.blob.length); - } + printf("level 0x%04x is %d bytes - %s\n", + io.in.level, io.out.blob.length, nt_errstr(status)); + dump_data(1, io.out.blob.data, io.out.blob.length); } } diff --git a/source4/torture/smb2/util.c b/source4/torture/smb2/util.c new file mode 100644 index 0000000000..7c4c99e777 --- /dev/null +++ b/source4/torture/smb2/util.c @@ -0,0 +1,199 @@ +/* + Unix SMB/CIFS implementation. + + helper functions for SMB2 test suite + + Copyright (C) Andrew Tridgell 2005 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" +#include "lib/cmdline/popt_common.h" +#include "lib/events/events.h" + +/* + show lots of information about a file +*/ +void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle) +{ + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_new(tree); + union smb2_fileinfo io; + + status = smb2_getinfo_level(tree, tmp_ctx, handle, SMB2_GETINFO_FILE_ALL_INFO, &io); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("getinfo failed - %s\n", nt_errstr(status))); + talloc_free(tmp_ctx); + return; + } + + d_printf("\tcreate_time: %s\n", nt_time_string(tmp_ctx, io.all_info.create_time)); + d_printf("\taccess_time: %s\n", nt_time_string(tmp_ctx, io.all_info.access_time)); + d_printf("\twrite_time: %s\n", nt_time_string(tmp_ctx, io.all_info.write_time)); + d_printf("\tchange_time: %s\n", nt_time_string(tmp_ctx, io.all_info.change_time)); + d_printf("\tattrib: 0x%x\n", io.all_info.file_attr); + d_printf("\talloc_size: %llu\n", (uint64_t)io.all_info.alloc_size); + d_printf("\tsize: %llu\n", (uint64_t)io.all_info.size); + d_printf("\tnlink: %u\n", io.all_info.nlink); + d_printf("\tdelete_pending: %u\n", io.all_info.delete_pending); + d_printf("\tdirectory: %u\n", io.all_info.directory); + d_printf("\tfile_id: %llu\n", io.all_info.file_id); + d_printf("\tea_size: %u\n", io.all_info.ea_size); + d_printf("\taccess_mask: 0x%08x\n", io.all_info.access_mask); + d_printf("\tunknown5: 0x%llx\n", io.all_info.unknown5); + d_printf("\tunknown6: 0x%llx\n", io.all_info.unknown6); + d_printf("\tfname: '%s'\n", io.all_info.fname); + + talloc_free(tmp_ctx); +} + + +/* + open a smb2 connection +*/ +BOOL torture_smb2_connection(TALLOC_CTX *mem_ctx, struct smb2_tree **tree) +{ + NTSTATUS status; + const char *host = lp_parm_string(-1, "torture", "host"); + const char *share = lp_parm_string(-1, "torture", "share"); + struct cli_credentials *credentials = cmdline_credentials; + + status = smb2_connect(mem_ctx, host, share, credentials, tree, + event_context_find(mem_ctx)); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to connect to SMB2 share \\\\%s\\%s - %s\n", + host, share, nt_errstr(status)); + return False; + } + return True; +} + + +/* + create and return a handle to a test file +*/ +NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname, + struct smb2_handle *handle) +{ + struct smb2_create io; + struct smb2_read r; + NTSTATUS status; + + ZERO_STRUCT(io); + io.in.buffer_code = 0x39; + io.in.oplock_flags = 0; + io.in.access_mask = SEC_RIGHTS_FILE_ALL; + io.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io.in.share_access = + NTCREATEX_SHARE_ACCESS_DELETE| + NTCREATEX_SHARE_ACCESS_READ| + NTCREATEX_SHARE_ACCESS_WRITE; + io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE; + io.in.fname = fname; + + status = smb2_create(tree, &io); + NT_STATUS_NOT_OK_RETURN(status); + + *handle = io.out.handle; + + ZERO_STRUCT(r); + r.in.buffer_code = 0x31; + r.in.length = 5; + r.in.offset = 0; + r.in.handle = *handle; + + smb2_read(tree, tree, &r); + + return NT_STATUS_OK; +} + +/* + create and return a handle to a test directory +*/ +NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname, + struct smb2_handle *handle) +{ + struct smb2_create io; + NTSTATUS status; + + ZERO_STRUCT(io); + io.in.buffer_code = 0x39; + io.in.oplock_flags = 0; + io.in.access_mask = SEC_RIGHTS_DIR_ALL; + io.in.file_attr = FILE_ATTRIBUTE_DIRECTORY; + io.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE; + io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.in.fname = fname; + + status = smb2_create(tree, &io); + NT_STATUS_NOT_OK_RETURN(status); + + *handle = io.out.handle; + + return NT_STATUS_OK; +} + + +/* + create a complex file using the old SMB protocol, to make it easier to + find fields in SMB2 getinfo levels +*/ +BOOL torture_setup_complex_file(const char *fname) +{ + struct smbcli_state *cli; + int fnum; + + if (!torture_open_connection(&cli)) { + return False; + } + + fnum = create_complex_file(cli, cli, fname); + + if (DEBUGLVL(1)) { + torture_all_info(cli->tree, fname); + } + + talloc_free(cli); + return fnum != -1; +} + +/* + create a complex directory using the old SMB protocol, to make it easier to + find fields in SMB2 getinfo levels +*/ +BOOL torture_setup_complex_dir(const char *dname) +{ + struct smbcli_state *cli; + int fnum; + + if (!torture_open_connection(&cli)) { + return False; + } + + fnum = create_complex_dir(cli, cli, dname); + + if (DEBUGLVL(1)) { + torture_all_info(cli->tree, dname); + } + + talloc_free(cli); + return fnum != -1; +} -- cgit