be friendlier in smb2_deltree to some of the SMB2 implementations that
[Samba.git] / source3 / torture / scanner.c
blob21b32dcf23e8dcae37c3db58066877246f02d7cb
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester - scanning functions
4 Copyright (C) Andrew Tridgell 2001
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 #define VERBOSE 0
23 #define OP_MIN 0
24 #define OP_MAX 20
26 #define DATA_SIZE 1024
27 #define PARAM_SIZE 1024
29 /****************************************************************************
30 look for a partial hit
31 ****************************************************************************/
32 static void trans2_check_hit(const char *format, int op, int level, NTSTATUS status)
34 if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
35 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
36 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
37 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
38 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
39 return;
41 #if VERBOSE
42 printf("possible %s hit op=%3d level=%5d status=%s\n",
43 format, op, level, nt_errstr(status));
44 #endif
47 /****************************************************************************
48 check for existance of a trans2 call
49 ****************************************************************************/
50 static NTSTATUS try_trans2(struct cli_state *cli,
51 int op,
52 char *param, char *data,
53 int param_len, int data_len,
54 unsigned int *rparam_len, unsigned int *rdata_len)
56 uint16 setup = op;
57 char *rparam=NULL, *rdata=NULL;
59 if (!cli_send_trans(cli, SMBtrans2,
60 NULL, /* name */
61 -1, 0, /* fid, flags */
62 &setup, 1, 0, /* setup, length, max */
63 param, param_len, 2, /* param, length, max */
64 data, data_len, cli->max_xmit /* data, length, max */
65 )) {
66 return cli_nt_error(cli);
69 cli_receive_trans(cli, SMBtrans2,
70 &rparam, rparam_len,
71 &rdata, rdata_len);
73 SAFE_FREE(rdata);
74 SAFE_FREE(rparam);
76 return cli_nt_error(cli);
80 static NTSTATUS try_trans2_len(struct cli_state *cli,
81 const char *format,
82 int op, int level,
83 char *param, char *data,
84 int param_len, int *data_len,
85 unsigned int *rparam_len, unsigned int *rdata_len)
87 NTSTATUS ret=NT_STATUS_OK;
89 ret = try_trans2(cli, op, param, data, param_len,
90 DATA_SIZE, rparam_len, rdata_len);
91 #if VERBOSE
92 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
93 #endif
94 if (!NT_STATUS_IS_OK(ret)) return ret;
96 *data_len = 0;
97 while (*data_len < DATA_SIZE) {
98 ret = try_trans2(cli, op, param, data, param_len,
99 *data_len, rparam_len, rdata_len);
100 if (NT_STATUS_IS_OK(ret)) break;
101 *data_len += 2;
103 if (NT_STATUS_IS_OK(ret)) {
104 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
105 format, level, *data_len, *rparam_len, *rdata_len);
106 } else {
107 trans2_check_hit(format, op, level, ret);
109 return ret;
112 /****************************************************************************
113 check for existance of a trans2 call
114 ****************************************************************************/
115 static bool scan_trans2(struct cli_state *cli, int op, int level,
116 int fnum, int dnum, const char *fname)
118 int data_len = 0;
119 int param_len = 0;
120 unsigned int rparam_len, rdata_len;
121 char param[PARAM_SIZE], data[DATA_SIZE];
122 NTSTATUS status;
124 memset(data, 0, sizeof(data));
125 data_len = 4;
127 /* try with a info level only */
128 param_len = 2;
129 SSVAL(param, 0, level);
130 status = try_trans2_len(cli, "void", op, level, param, data, param_len, &data_len,
131 &rparam_len, &rdata_len);
132 if (NT_STATUS_IS_OK(status)) return True;
134 /* try with a file descriptor */
135 param_len = 6;
136 SSVAL(param, 0, fnum);
137 SSVAL(param, 2, level);
138 SSVAL(param, 4, 0);
139 status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len,
140 &rparam_len, &rdata_len);
141 if (NT_STATUS_IS_OK(status)) return True;
144 /* try with a notify style */
145 param_len = 6;
146 SSVAL(param, 0, dnum);
147 SSVAL(param, 2, dnum);
148 SSVAL(param, 4, level);
149 status = try_trans2_len(cli, "notify", op, level, param, data, param_len, &data_len,
150 &rparam_len, &rdata_len);
151 if (NT_STATUS_IS_OK(status)) return True;
153 /* try with a file name */
154 param_len = 6;
155 SSVAL(param, 0, level);
156 SSVAL(param, 2, 0);
157 SSVAL(param, 4, 0);
158 param_len += clistr_push(cli, &param[6], fname, -1, STR_TERMINATE);
160 status = try_trans2_len(cli, "fname", op, level, param, data, param_len, &data_len,
161 &rparam_len, &rdata_len);
162 if (NT_STATUS_IS_OK(status)) return True;
164 /* try with a new file name */
165 param_len = 6;
166 SSVAL(param, 0, level);
167 SSVAL(param, 2, 0);
168 SSVAL(param, 4, 0);
169 param_len += clistr_push(cli, &param[6], "\\newfile.dat", -1, STR_TERMINATE);
171 status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len,
172 &rparam_len, &rdata_len);
173 cli_unlink(cli, "\\newfile.dat");
174 cli_rmdir(cli, "\\newfile.dat");
175 if (NT_STATUS_IS_OK(status)) return True;
177 /* try dfs style */
178 cli_mkdir(cli, "\\testdir");
179 param_len = 2;
180 SSVAL(param, 0, level);
181 param_len += clistr_push(cli, &param[2], "\\testdir", -1, STR_TERMINATE);
183 status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len,
184 &rparam_len, &rdata_len);
185 cli_rmdir(cli, "\\testdir");
186 if (NT_STATUS_IS_OK(status)) return True;
188 return False;
192 bool torture_trans2_scan(int dummy)
194 static struct cli_state *cli;
195 int op, level;
196 const char *fname = "\\scanner.dat";
197 int fnum, dnum;
199 printf("starting trans2 scan test\n");
201 if (!torture_open_connection(&cli, 0)) {
202 return False;
205 fnum = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
206 DENY_NONE);
207 dnum = cli_open(cli, "\\", O_RDONLY, DENY_NONE);
209 for (op=OP_MIN; op<=OP_MAX; op++) {
210 printf("Scanning op=%d\n", op);
211 for (level = 0; level <= 50; level++) {
212 scan_trans2(cli, op, level, fnum, dnum, fname);
215 for (level = 0x100; level <= 0x130; level++) {
216 scan_trans2(cli, op, level, fnum, dnum, fname);
219 for (level = 1000; level < 1050; level++) {
220 scan_trans2(cli, op, level, fnum, dnum, fname);
224 torture_close_connection(cli);
226 printf("trans2 scan finished\n");
227 return True;
233 /****************************************************************************
234 look for a partial hit
235 ****************************************************************************/
236 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
238 if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
239 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
240 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
241 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
242 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
243 return;
245 #if VERBOSE
246 printf("possible %s hit op=%3d level=%5d status=%s\n",
247 format, op, level, nt_errstr(status));
248 #endif
251 /****************************************************************************
252 check for existance of a nttrans call
253 ****************************************************************************/
254 static NTSTATUS try_nttrans(struct cli_state *cli,
255 int op,
256 char *param, char *data,
257 int param_len, int data_len,
258 unsigned int *rparam_len, unsigned int *rdata_len)
260 char *rparam=NULL, *rdata=NULL;
262 if (!cli_send_nt_trans(cli, op,
264 NULL, 0, 0,
265 param, param_len, 2, /* param, length, max */
266 data, data_len, cli->max_xmit /* data, length, max */
267 )) {
268 return cli_nt_error(cli);
271 cli_receive_nt_trans(cli,
272 &rparam, rparam_len,
273 &rdata, rdata_len);
275 SAFE_FREE(rdata);
276 SAFE_FREE(rparam);
278 return cli_nt_error(cli);
282 static NTSTATUS try_nttrans_len(struct cli_state *cli,
283 const char *format,
284 int op, int level,
285 char *param, char *data,
286 int param_len, int *data_len,
287 unsigned int *rparam_len, unsigned int *rdata_len)
289 NTSTATUS ret=NT_STATUS_OK;
291 ret = try_nttrans(cli, op, param, data, param_len,
292 DATA_SIZE, rparam_len, rdata_len);
293 #if VERBOSE
294 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
295 #endif
296 if (!NT_STATUS_IS_OK(ret)) return ret;
298 *data_len = 0;
299 while (*data_len < DATA_SIZE) {
300 ret = try_nttrans(cli, op, param, data, param_len,
301 *data_len, rparam_len, rdata_len);
302 if (NT_STATUS_IS_OK(ret)) break;
303 *data_len += 2;
305 if (NT_STATUS_IS_OK(ret)) {
306 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
307 format, level, *data_len, *rparam_len, *rdata_len);
308 } else {
309 nttrans_check_hit(format, op, level, ret);
311 return ret;
314 /****************************************************************************
315 check for existance of a nttrans call
316 ****************************************************************************/
317 static bool scan_nttrans(struct cli_state *cli, int op, int level,
318 int fnum, int dnum, const char *fname)
320 int data_len = 0;
321 int param_len = 0;
322 unsigned int rparam_len, rdata_len;
323 char param[PARAM_SIZE], data[DATA_SIZE];
324 NTSTATUS status;
326 memset(data, 0, sizeof(data));
327 data_len = 4;
329 /* try with a info level only */
330 param_len = 2;
331 SSVAL(param, 0, level);
332 status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len,
333 &rparam_len, &rdata_len);
334 if (NT_STATUS_IS_OK(status)) return True;
336 /* try with a file descriptor */
337 param_len = 6;
338 SSVAL(param, 0, fnum);
339 SSVAL(param, 2, level);
340 SSVAL(param, 4, 0);
341 status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len,
342 &rparam_len, &rdata_len);
343 if (NT_STATUS_IS_OK(status)) return True;
346 /* try with a notify style */
347 param_len = 6;
348 SSVAL(param, 0, dnum);
349 SSVAL(param, 2, dnum);
350 SSVAL(param, 4, level);
351 status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len,
352 &rparam_len, &rdata_len);
353 if (NT_STATUS_IS_OK(status)) return True;
355 /* try with a file name */
356 param_len = 6;
357 SSVAL(param, 0, level);
358 SSVAL(param, 2, 0);
359 SSVAL(param, 4, 0);
360 param_len += clistr_push(cli, &param[6], fname, -1, STR_TERMINATE);
362 status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len,
363 &rparam_len, &rdata_len);
364 if (NT_STATUS_IS_OK(status)) return True;
366 /* try with a new file name */
367 param_len = 6;
368 SSVAL(param, 0, level);
369 SSVAL(param, 2, 0);
370 SSVAL(param, 4, 0);
371 param_len += clistr_push(cli, &param[6], "\\newfile.dat", -1, STR_TERMINATE);
373 status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len,
374 &rparam_len, &rdata_len);
375 cli_unlink(cli, "\\newfile.dat");
376 cli_rmdir(cli, "\\newfile.dat");
377 if (NT_STATUS_IS_OK(status)) return True;
379 /* try dfs style */
380 cli_mkdir(cli, "\\testdir");
381 param_len = 2;
382 SSVAL(param, 0, level);
383 param_len += clistr_push(cli, &param[2], "\\testdir", -1, STR_TERMINATE);
385 status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len,
386 &rparam_len, &rdata_len);
387 cli_rmdir(cli, "\\testdir");
388 if (NT_STATUS_IS_OK(status)) return True;
390 return False;
394 bool torture_nttrans_scan(int dummy)
396 static struct cli_state *cli;
397 int op, level;
398 const char *fname = "\\scanner.dat";
399 int fnum, dnum;
401 printf("starting nttrans scan test\n");
403 if (!torture_open_connection(&cli, 0)) {
404 return False;
407 fnum = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
408 DENY_NONE);
409 dnum = cli_open(cli, "\\", O_RDONLY, DENY_NONE);
411 for (op=OP_MIN; op<=OP_MAX; op++) {
412 printf("Scanning op=%d\n", op);
413 for (level = 0; level <= 50; level++) {
414 scan_nttrans(cli, op, level, fnum, dnum, fname);
417 for (level = 0x100; level <= 0x130; level++) {
418 scan_nttrans(cli, op, level, fnum, dnum, fname);
421 for (level = 1000; level < 1050; level++) {
422 scan_nttrans(cli, op, level, fnum, dnum, fname);
426 torture_close_connection(cli);
428 printf("nttrans scan finished\n");
429 return True;