adb7fdb7f1aeee95df1f4993fb53e49bcf56e430
[samba.git] / source4 / torture / smb2 / scan.c
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 "torture/torture.h"
27 #include "param/param.h"
28 #include "libcli/resolve/resolve.h"
29
30 #include "torture/smb2/proto.h"
31
32 /* 
33    scan for valid SMB2 getinfo levels
34 */
35 static bool torture_smb2_getinfo_scan(struct torture_context *tctx)
36 {
37         struct smb2_tree *tree;
38         NTSTATUS status;
39         struct smb2_getinfo io;
40         struct smb2_handle fhandle, dhandle;
41         int c, i;
42
43         static const char *FNAME  = "scan-getinfo.dat";
44         static const char *FNAME2 = "scan-getinfo.dat:2ndstream";
45         static const char *DNAME  = "scan-getinfo.dir";
46         static const char *DNAME2 = "scan-getinfo.dir:2ndstream";
47
48         if (!torture_smb2_connection(tctx, &tree)) {
49                 return false;
50         }
51
52         status = torture_setup_complex_file(tctx, tree, FNAME);
53         if (!NT_STATUS_IS_OK(status)) {
54                 torture_comment(tctx, "Failed to setup complex file '%s': %s\n",
55                        FNAME, nt_errstr(status));
56                 return false;
57         }
58         torture_setup_complex_file(tctx, tree, FNAME2);
59
60         status = torture_setup_complex_dir(tctx, tree, DNAME);
61         if (!NT_STATUS_IS_OK(status)) {
62                 torture_comment(tctx, "Failed to setup complex dir '%s': %s\n",
63                        DNAME, nt_errstr(status));
64                 smb2_util_unlink(tree, FNAME);
65                 return false;
66         }
67         torture_setup_complex_file(tctx, tree, DNAME2);
68
69         torture_smb2_testfile(tree, FNAME, &fhandle);
70         torture_smb2_testdir(tree, DNAME, &dhandle);
71
72
73         ZERO_STRUCT(io);
74         io.in.output_buffer_length = 0xFFFF;
75
76         for (c=1;c<5;c++) {
77                 for (i=0;i<0x100;i++) {
78                         io.in.info_type = c;
79                         io.in.info_class = i;
80
81                         io.in.file.handle = fhandle;
82                         status = smb2_getinfo(tree, tctx, &io);
83                         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
84                                 torture_comment(tctx, "file level 0x%02x:%02x %u is %ld bytes - %s\n",
85                                        io.in.info_type, io.in.info_class, 
86                                        (unsigned)io.in.info_class, 
87                                        (long)io.out.blob.length, nt_errstr(status));
88                                 dump_data(1, io.out.blob.data, io.out.blob.length);
89                         }
90
91                         io.in.file.handle = dhandle;
92                         status = smb2_getinfo(tree, tctx, &io);
93                         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
94                                 torture_comment(tctx, "dir  level 0x%02x:%02x %u is %ld bytes - %s\n",
95                                        io.in.info_type, io.in.info_class,
96                                        (unsigned)io.in.info_class, 
97                                        (long)io.out.blob.length, nt_errstr(status));
98                                 dump_data(1, io.out.blob.data, io.out.blob.length);
99                         }
100                 }
101         }
102
103         smb2_util_unlink(tree, FNAME);
104         smb2_util_rmdir(tree, DNAME);
105         return true;
106 }
107
108 /* 
109    scan for valid SMB2 setinfo levels
110 */
111 static bool torture_smb2_setinfo_scan(struct torture_context *tctx)
112 {
113         static const char *FNAME  = "scan-setinfo.dat";
114         static const char *FNAME2 = "scan-setinfo.dat:2ndstream";
115
116         struct smb2_tree *tree;
117         NTSTATUS status;
118         struct smb2_setinfo io;
119         struct smb2_handle handle;
120         int c, i;
121
122         if (!torture_smb2_connection(tctx, &tree)) {
123                 return false;
124         }
125
126         status = torture_setup_complex_file(tctx, tree, FNAME);
127         if (!NT_STATUS_IS_OK(status)) {
128                 torture_comment(tctx, "Failed to setup complex file '%s': %s\n",
129                        FNAME, nt_errstr(status));
130                 return false;
131         }
132         torture_setup_complex_file(tctx, tree, FNAME2);
133
134         torture_smb2_testfile(tree, FNAME, &handle);
135
136         ZERO_STRUCT(io);
137         io.in.blob = data_blob_talloc_zero(tctx, 1024);
138
139         for (c=1;c<5;c++) {
140                 for (i=0;i<0x100;i++) {
141                         io.in.level = (i<<8) | c;
142                         io.in.file.handle = handle;
143                         status = smb2_setinfo(tree, &io);
144                         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
145                                 torture_comment(tctx, "file level 0x%04x - %s\n",
146                                        io.in.level, nt_errstr(status));
147                         }
148                 }
149         }
150
151         smb2_util_unlink(tree, FNAME);
152         return true;
153 }
154
155
156 /* 
157    scan for valid SMB2 scan levels
158 */
159 static bool torture_smb2_find_scan(struct torture_context *tctx)
160 {
161         struct smb2_tree *tree;
162         NTSTATUS status;
163         struct smb2_find io;
164         struct smb2_handle handle;
165         int i;
166
167         if (!torture_smb2_connection(tctx, &tree)) {
168                 return false;
169         }
170
171         torture_assert_ntstatus_ok(tctx,
172                 smb2_util_roothandle(tree, &handle),
173                 "Failed to open roothandle");
174
175         ZERO_STRUCT(io);
176         io.in.file.handle       = handle;
177         io.in.pattern           = "*";
178         io.in.continue_flags    = SMB2_CONTINUE_FLAG_RESTART;
179         io.in.max_response_size = 0x10000;
180
181         for (i=1;i<0x100;i++) {
182                 io.in.level = i;
183
184                 io.in.file.handle = handle;
185                 status = smb2_find(tree, tctx, &io);
186                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) &&
187                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) &&
188                     !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
189                         torture_comment(tctx, "find level 0x%04x is %ld bytes - %s\n",
190                                io.in.level, (long)io.out.blob.length, nt_errstr(status));
191                         dump_data(1, io.out.blob.data, io.out.blob.length);
192                 }
193         }
194
195         return true;
196 }
197
198 /* 
199    scan for valid SMB2 opcodes
200 */
201 static bool torture_smb2_scan(struct torture_context *tctx)
202 {
203         TALLOC_CTX *mem_ctx = talloc_new(tctx);
204         struct smb2_tree *tree;
205         const char *host = torture_setting_string(tctx, "host", NULL);
206         const char *share = torture_setting_string(tctx, "share", NULL);
207         NTSTATUS status;
208         int opcode;
209         struct smb2_request *req;
210         struct smbcli_options options;
211
212         lpcfg_smbcli_options(tctx->lp_ctx, &options);
213
214         status = smb2_connect(mem_ctx, host,
215                               lpcfg_smb_ports(tctx->lp_ctx),
216                               share,
217                               lpcfg_resolve_context(tctx->lp_ctx),
218                               popt_get_cmdline_credentials(),
219                               &tree, tctx->ev, &options,
220                               lpcfg_socket_options(tctx->lp_ctx),
221                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
222         torture_assert_ntstatus_ok(tctx, status, "Connection failed");
223
224         tree->session->transport->options.request_timeout = 3;
225
226         for (opcode=0;opcode<1000;opcode++) {
227                 req = smb2_request_init_tree(tree, opcode, 2, false, 0);
228                 SSVAL(req->out.body, 0, 0);
229                 smb2_transport_send(req);
230                 if (!smb2_request_receive(req)) {
231                         talloc_free(tree);
232                         status = smb2_connect(mem_ctx, host,
233                                               lpcfg_smb_ports(tctx->lp_ctx),
234                                               share,
235                                               lpcfg_resolve_context(tctx->lp_ctx),
236                                               popt_get_cmdline_credentials(),
237                                               &tree, tctx->ev, &options,
238                                               lpcfg_socket_options(tctx->lp_ctx),
239                                               lpcfg_gensec_settings(mem_ctx, tctx->lp_ctx));
240                         torture_assert_ntstatus_ok(tctx, status, "Connection failed");
241                         tree->session->transport->options.request_timeout = 3;
242                 } else {
243                         status = smb2_request_destroy(req);
244                         torture_comment(tctx, "active opcode %4d gave status %s\n", opcode, nt_errstr(status));
245                 }
246         }
247
248         talloc_free(mem_ctx);
249
250         return true;
251 }
252
253 struct torture_suite *torture_smb2_scan_init(TALLOC_CTX *ctx)
254 {
255         struct torture_suite *suite = torture_suite_create(ctx, "scan");
256
257         torture_suite_add_simple_test(suite, "scan", torture_smb2_scan);
258         torture_suite_add_simple_test(suite, "getinfo", torture_smb2_getinfo_scan);
259         torture_suite_add_simple_test(suite, "setinfo", torture_smb2_setinfo_scan);
260         torture_suite_add_simple_test(suite, "find", torture_smb2_find_scan);
261
262         suite->description = talloc_strdup(suite, "scan target (not a test)");
263
264         return suite;
265 }