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