s4:torture make a suite for smb2.*scan
[mat/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 *torture)
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(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': %s\n",
55                        FNAME, nt_errstr(status));
56                 return false;
57         }
58         torture_setup_complex_file(tree, FNAME2);
59
60         status = torture_setup_complex_dir(tree, DNAME);
61         if (!NT_STATUS_IS_OK(status)) {
62                 printf("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(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, torture, &io);
83                         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
84                                 printf("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, torture, &io);
93                         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
94                                 printf("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 *torture)
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(torture, &tree)) {
123                 return false;
124         }
125
126         status = torture_setup_complex_file(tree, FNAME);
127         if (!NT_STATUS_IS_OK(status)) {
128                 printf("Failed to setup complex file '%s': %s\n",
129                        FNAME, nt_errstr(status));
130                 return false;
131         }
132         torture_setup_complex_file(tree, FNAME2);
133
134         torture_smb2_testfile(tree, FNAME, &handle);
135
136         ZERO_STRUCT(io);
137         io.in.blob = data_blob_talloc_zero(torture, 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                                 printf("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 *torture)
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(torture, &tree)) {
168                 return false;
169         }
170
171         status = smb2_util_roothandle(tree, &handle);
172         if (!NT_STATUS_IS_OK(status)) {
173                 printf("Failed to open roothandle - %s\n", nt_errstr(status));
174                 return false;
175         }
176
177         ZERO_STRUCT(io);
178         io.in.file.handle       = handle;
179         io.in.pattern           = "*";
180         io.in.continue_flags    = SMB2_CONTINUE_FLAG_RESTART;
181         io.in.max_response_size = 0x10000;
182
183         for (i=1;i<0x100;i++) {
184                 io.in.level = i;
185
186                 io.in.file.handle = handle;
187                 status = smb2_find(tree, torture, &io);
188                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) &&
189                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) &&
190                     !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
191                         printf("find level 0x%04x is %ld bytes - %s\n", 
192                                io.in.level, (long)io.out.blob.length, nt_errstr(status));
193                         dump_data(1, io.out.blob.data, io.out.blob.length);
194                 }
195         }
196
197         return true;
198 }
199
200 /* 
201    scan for valid SMB2 opcodes
202 */
203 static bool torture_smb2_scan(struct torture_context *torture)
204 {
205         TALLOC_CTX *mem_ctx = talloc_new(NULL);
206         struct smb2_tree *tree;
207         const char *host = torture_setting_string(torture, "host", NULL);
208         const char *share = torture_setting_string(torture, "share", NULL);
209         struct cli_credentials *credentials = cmdline_credentials;
210         NTSTATUS status;
211         int opcode;
212         struct smb2_request *req;
213         struct smbcli_options options;
214
215         lpcfg_smbcli_options(torture->lp_ctx, &options);
216
217         status = smb2_connect(mem_ctx, host, 
218                                                   lpcfg_smb_ports(torture->lp_ctx),
219                                                   share, 
220                                                   lpcfg_resolve_context(torture->lp_ctx),
221                                                   credentials, &tree, torture->ev, &options,
222                                                   lpcfg_socket_options(torture->lp_ctx),
223                                                   lpcfg_gensec_settings(torture, torture->lp_ctx));
224         if (!NT_STATUS_IS_OK(status)) {
225                 printf("Connection failed - %s\n", nt_errstr(status));
226                 return false;
227         }
228
229         tree->session->transport->options.request_timeout = 3;
230
231         for (opcode=0;opcode<1000;opcode++) {
232                 req = smb2_request_init_tree(tree, opcode, 2, false, 0);
233                 SSVAL(req->out.body, 0, 0);
234                 smb2_transport_send(req);
235                 if (!smb2_request_receive(req)) {
236                         talloc_free(tree);
237                         status = smb2_connect(mem_ctx, host, 
238                                                                   lpcfg_smb_ports(torture->lp_ctx),
239                                                                   share, 
240                                                                   lpcfg_resolve_context(torture->lp_ctx),
241                                                                   credentials, &tree, torture->ev, &options,
242                                                                   lpcfg_socket_options(torture->lp_ctx),
243                                                                   lpcfg_gensec_settings(mem_ctx, torture->lp_ctx));
244                         if (!NT_STATUS_IS_OK(status)) {
245                                 printf("Connection failed - %s\n", nt_errstr(status));
246                                 return false;
247                         }
248                         tree->session->transport->options.request_timeout = 3;
249                 } else {
250                         status = smb2_request_destroy(req);
251                         printf("active opcode %4d gave status %s\n", opcode, nt_errstr(status));
252                 }
253         }
254
255         talloc_free(mem_ctx);
256
257         return true;
258 }
259
260 struct torture_suite *torture_smb2_scan_init(void)
261 {
262         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "scan");
263
264         torture_suite_add_simple_test(suite, "scan", torture_smb2_scan);
265         torture_suite_add_simple_test(suite, "getinfo", torture_smb2_getinfo_scan);
266         torture_suite_add_simple_test(suite, "setinfo", torture_smb2_setinfo_scan);
267         torture_suite_add_simple_test(suite, "find", torture_smb2_find_scan);
268
269         suite->description = talloc_strdup(suite, "scan target (not a test)");
270
271         return suite;
272 }