1/* 2 Unix SMB/CIFS implementation. 3 4 SMB2 opcode scanner 5 6 Copyright (C) Andrew Tridgell 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "libcli/smb2/smb2.h" 24#include "libcli/smb2/smb2_calls.h" 25#include "lib/cmdline/popt_common.h" 26#include "lib/events/events.h" 27#include "torture/torture.h" 28#include "param/param.h" 29#include "libcli/resolve/resolve.h" 30 31#include "torture/smb2/proto.h" 32 33#define FNAME "scan-getinfo.dat" 34#define DNAME "scan-getinfo.dir" 35 36 37/* 38 scan for valid SMB2 getinfo levels 39*/ 40bool torture_smb2_getinfo_scan(struct torture_context *torture) 41{ 42 struct smb2_tree *tree; 43 NTSTATUS status; 44 struct smb2_getinfo io; 45 struct smb2_handle fhandle, dhandle; 46 int c, i; 47 48 if (!torture_smb2_connection(torture, &tree)) { 49 return false; 50 } 51 52 status = torture_setup_complex_file(tree, FNAME); 53 if (!NT_STATUS_IS_OK(status)) { 54 printf("Failed to setup complex file '%s'\n", FNAME); 55 return false; 56 } 57 torture_setup_complex_file(tree, FNAME ":2ndstream"); 58 59 status = torture_setup_complex_dir(tree, DNAME); 60 if (!NT_STATUS_IS_OK(status)) { 61 printf("Failed to setup complex dir '%s'\n", DNAME); 62 return false; 63 } 64 torture_setup_complex_file(tree, DNAME ":2ndstream"); 65 66 torture_smb2_testfile(tree, FNAME, &fhandle); 67 torture_smb2_testdir(tree, DNAME, &dhandle); 68 69 70 ZERO_STRUCT(io); 71 io.in.output_buffer_length = 0xFFFF; 72 73 for (c=1;c<5;c++) { 74 for (i=0;i<0x100;i++) { 75 io.in.info_type = c; 76 io.in.info_class = i; 77 78 io.in.file.handle = fhandle; 79 status = smb2_getinfo(tree, torture, &io); 80 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { 81 printf("file level 0x%02x:%02x %u is %ld bytes - %s\n", 82 io.in.info_type, io.in.info_class, 83 (unsigned)io.in.info_class, 84 (long)io.out.blob.length, nt_errstr(status)); 85 dump_data(1, io.out.blob.data, io.out.blob.length); 86 } 87 88 io.in.file.handle = dhandle; 89 status = smb2_getinfo(tree, torture, &io); 90 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { 91 printf("dir level 0x%02x:%02x %u is %ld bytes - %s\n", 92 io.in.info_type, io.in.info_class, 93 (unsigned)io.in.info_class, 94 (long)io.out.blob.length, nt_errstr(status)); 95 dump_data(1, io.out.blob.data, io.out.blob.length); 96 } 97 } 98 } 99 100 return true; 101} 102 103/* 104 scan for valid SMB2 setinfo levels 105*/ 106bool torture_smb2_setinfo_scan(struct torture_context *torture) 107{ 108 struct smb2_tree *tree; 109 NTSTATUS status; 110 struct smb2_setinfo io; 111 struct smb2_handle handle; 112 int c, i; 113 114 if (!torture_smb2_connection(torture, &tree)) { 115 return false; 116 } 117 118 status = torture_setup_complex_file(tree, FNAME); 119 if (!NT_STATUS_IS_OK(status)) { 120 printf("Failed to setup complex file '%s'\n", FNAME); 121 return false; 122 } 123 torture_setup_complex_file(tree, FNAME ":2ndstream"); 124 125 torture_smb2_testfile(tree, FNAME, &handle); 126 127 ZERO_STRUCT(io); 128 io.in.blob = data_blob_talloc_zero(torture, 1024); 129 130 for (c=1;c<5;c++) { 131 for (i=0;i<0x100;i++) { 132 io.in.level = (i<<8) | c; 133 io.in.file.handle = handle; 134 status = smb2_setinfo(tree, &io); 135 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { 136 printf("file level 0x%04x - %s\n", 137 io.in.level, nt_errstr(status)); 138 } 139 } 140 } 141 142 return true; 143} 144 145 146/* 147 scan for valid SMB2 scan levels 148*/ 149bool torture_smb2_find_scan(struct torture_context *torture) 150{ 151 struct smb2_tree *tree; 152 NTSTATUS status; 153 struct smb2_find io; 154 struct smb2_handle handle; 155 int i; 156 157 if (!torture_smb2_connection(torture, &tree)) { 158 return false; 159 } 160 161 status = smb2_util_roothandle(tree, &handle); 162 if (!NT_STATUS_IS_OK(status)) { 163 printf("Failed to open roothandle - %s\n", nt_errstr(status)); 164 return false; 165 } 166 167 ZERO_STRUCT(io); 168 io.in.file.handle = handle; 169 io.in.pattern = "*"; 170 io.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART; 171 io.in.max_response_size = 0x10000; 172 173 for (i=1;i<0x100;i++) { 174 io.in.level = i; 175 176 io.in.file.handle = handle; 177 status = smb2_find(tree, torture, &io); 178 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) && 179 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) && 180 !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { 181 printf("find level 0x%04x is %ld bytes - %s\n", 182 io.in.level, (long)io.out.blob.length, nt_errstr(status)); 183 dump_data(1, io.out.blob.data, io.out.blob.length); 184 } 185 } 186 187 return true; 188} 189 190/* 191 scan for valid SMB2 opcodes 192*/ 193bool torture_smb2_scan(struct torture_context *torture) 194{ 195 TALLOC_CTX *mem_ctx = talloc_new(NULL); 196 struct smb2_tree *tree; 197 const char *host = torture_setting_string(torture, "host", NULL); 198 const char *share = torture_setting_string(torture, "share", NULL); 199 struct cli_credentials *credentials = cmdline_credentials; 200 NTSTATUS status; 201 int opcode; 202 struct smb2_request *req; 203 struct smbcli_options options; 204 205 lp_smbcli_options(torture->lp_ctx, &options); 206 207 status = smb2_connect(mem_ctx, host, 208 lp_smb_ports(torture->lp_ctx), 209 share, 210 lp_resolve_context(torture->lp_ctx), 211 credentials, &tree, torture->ev, &options, 212 lp_socket_options(torture->lp_ctx), 213 lp_gensec_settings(torture, torture->lp_ctx)); 214 if (!NT_STATUS_IS_OK(status)) { 215 printf("Connection failed - %s\n", nt_errstr(status)); 216 return false; 217 } 218 219 tree->session->transport->options.request_timeout = 3; 220 221 for (opcode=0;opcode<1000;opcode++) { 222 req = smb2_request_init_tree(tree, opcode, 2, false, 0); 223 SSVAL(req->out.body, 0, 0); 224 smb2_transport_send(req); 225 if (!smb2_request_receive(req)) { 226 talloc_free(tree); 227 status = smb2_connect(mem_ctx, host, 228 lp_smb_ports(torture->lp_ctx), 229 share, 230 lp_resolve_context(torture->lp_ctx), 231 credentials, &tree, torture->ev, &options, 232 lp_socket_options(torture->lp_ctx), 233 lp_gensec_settings(mem_ctx, torture->lp_ctx)); 234 if (!NT_STATUS_IS_OK(status)) { 235 printf("Connection failed - %s\n", nt_errstr(status)); 236 return false; 237 } 238 tree->session->transport->options.request_timeout = 3; 239 } else { 240 status = smb2_request_destroy(req); 241 printf("active opcode %4d gave status %s\n", opcode, nt_errstr(status)); 242 } 243 } 244 245 talloc_free(mem_ctx); 246 247 return true; 248} 249