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/>.
21 #include "system/filesys.h"
22 #include "torture/proto.h"
23 #include "libsmb/libsmb.h"
24 #include "../libcli/smb/smbXcli_base.h"
30 #define DATA_SIZE 1024
31 #define PARAM_SIZE 1024
33 /****************************************************************************
34 look for a partial hit
35 ****************************************************************************/
36 static void trans2_check_hit(const char *format
, int op
, int level
, NTSTATUS status
)
38 if (NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL
) ||
39 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED
) ||
40 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED
) ||
41 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL
) ||
42 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS
)) {
46 printf("possible %s hit op=%3d level=%5d status=%s\n",
47 format
, op
, level
, nt_errstr(status
));
51 /****************************************************************************
52 check for existence of a trans2 call
53 ****************************************************************************/
54 static NTSTATUS
try_trans2(struct cli_state
*cli
,
56 uint8_t *param
, uint8_t *data
,
57 uint32_t param_len
, uint32_t data_len
,
58 uint32_t *rparam_len
, uint32_t *rdata_len
)
61 uint8_t *rparam
=NULL
, *rdata
=NULL
;
64 SSVAL(setup
+0, 0, op
);
66 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
,
67 NULL
, -1, /* name, fid */
69 NULL
, 0, 0, /* setup */
71 data
, data_len
, CLI_BUFFER_SIZE
,
72 NULL
, /* recv_flags2 */
73 NULL
, 0, NULL
, /* rsetup */
74 &rparam
, 0, rparam_len
,
75 &rdata
, 0, rdata_len
);
84 static NTSTATUS
try_trans2_len(struct cli_state
*cli
,
87 uint8_t *param
, uint8_t *data
,
88 uint32_t param_len
, uint32_t *data_len
,
89 uint32_t *rparam_len
, uint32_t *rdata_len
)
91 NTSTATUS ret
=NT_STATUS_OK
;
93 ret
= try_trans2(cli
, op
, param
, data
, param_len
,
94 DATA_SIZE
, rparam_len
, rdata_len
);
96 printf("op=%d level=%d ret=%s\n", op
, level
, nt_errstr(ret
));
98 if (!NT_STATUS_IS_OK(ret
)) return ret
;
101 while (*data_len
< DATA_SIZE
) {
102 ret
= try_trans2(cli
, op
, param
, data
, param_len
,
103 *data_len
, rparam_len
, rdata_len
);
104 if (NT_STATUS_IS_OK(ret
)) break;
107 if (NT_STATUS_IS_OK(ret
)) {
108 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
109 format
, level
, *data_len
, *rparam_len
, *rdata_len
);
111 trans2_check_hit(format
, op
, level
, ret
);
116 /****************************************************************************
117 check for existence of a trans2 call
118 ****************************************************************************/
119 static bool scan_trans2(struct cli_state
*cli
, int op
, int level
,
120 int fnum
, int dnum
, const char *fname
)
122 uint32_t data_len
= 0;
123 uint32_t param_len
= 0;
124 uint32_t rparam_len
, rdata_len
;
125 uint8_t *param
= NULL
;
126 uint8_t data
[DATA_SIZE
];
127 const char *newfname
;
131 memset(data
, 0, sizeof(data
));
134 /* try with a info level only */
136 param
= talloc_array(talloc_tos(), uint8_t, 2);
137 if (param
== NULL
) return True
;
139 SSVAL(param
, 0, level
);
141 param_len
= talloc_get_size(param
);
142 status
= try_trans2_len(cli
, "void", op
, level
, param
, data
, param_len
, &data_len
,
143 &rparam_len
, &rdata_len
);
144 if (NT_STATUS_IS_OK(status
)) return True
;
146 /* try with a file descriptor */
148 param
= talloc_array(talloc_tos(), uint8_t, 6);
149 if (param
== NULL
) return True
;
151 SSVAL(param
, 0, fnum
);
152 SSVAL(param
, 2, level
);
155 param_len
= talloc_get_size(param
);
156 status
= try_trans2_len(cli
, "fnum", op
, level
, param
, data
, param_len
, &data_len
,
157 &rparam_len
, &rdata_len
);
158 if (NT_STATUS_IS_OK(status
)) return True
;
161 /* try with a notify style */
163 param
= talloc_array(talloc_tos(), uint8_t, 6);
164 if (param
== NULL
) return True
;
166 SSVAL(param
, 0, dnum
);
167 SSVAL(param
, 2, dnum
);
168 SSVAL(param
, 4, level
);
170 param_len
= talloc_get_size(param
);
171 status
= try_trans2_len(cli
, "notify", op
, level
, param
, data
, param_len
, &data_len
,
172 &rparam_len
, &rdata_len
);
173 if (NT_STATUS_IS_OK(status
)) return True
;
175 /* try with a file name */
177 param
= talloc_array(talloc_tos(), uint8_t, 6);
178 if (param
== NULL
) return True
;
180 SSVAL(param
, 0, level
);
183 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
184 fname
, strlen(fname
)+1, NULL
);
185 if (param
== NULL
) return True
;
187 param_len
= talloc_get_size(param
);
188 status
= try_trans2_len(cli
, "fname", op
, level
, param
, data
, param_len
, &data_len
,
189 &rparam_len
, &rdata_len
);
190 if (NT_STATUS_IS_OK(status
)) return True
;
192 /* try with a new file name */
193 newfname
= "\\newfile.dat";
195 param
= talloc_array(talloc_tos(), uint8_t, 6);
196 if (param
== NULL
) return True
;
198 SSVAL(param
, 0, level
);
201 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
202 newfname
, strlen(newfname
)+1, NULL
);
203 if (param
== NULL
) return True
;
205 param_len
= talloc_get_size(param
);
206 status
= try_trans2_len(cli
, "newfile", op
, level
, param
, data
, param_len
, &data_len
,
207 &rparam_len
, &rdata_len
);
208 cli_unlink(cli
, newfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
209 cli_rmdir(cli
, newfname
);
210 if (NT_STATUS_IS_OK(status
)) return True
;
214 cli_mkdir(cli
, dname
);
216 param
= talloc_array(talloc_tos(), uint8_t, 2);
217 if (param
== NULL
) return True
;
219 SSVAL(param
, 0, level
);
220 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
221 dname
, strlen(dname
)+1, NULL
);
222 if (param
== NULL
) return True
;
224 param_len
= talloc_get_size(param
);
225 status
= try_trans2_len(cli
, "dfs", op
, level
, param
, data
, param_len
, &data_len
,
226 &rparam_len
, &rdata_len
);
227 cli_rmdir(cli
, dname
);
228 if (NT_STATUS_IS_OK(status
)) return True
;
234 bool torture_trans2_scan(int dummy
)
236 static struct cli_state
*cli
;
238 const char *fname
= "\\scanner.dat";
241 printf("starting trans2 scan test\n");
243 if (!torture_open_connection(&cli
, 0)) {
247 if (!NT_STATUS_IS_OK(cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
,
248 DENY_NONE
, &fnum
))) {
249 printf("open of %s failed\n", fname
);
252 if (!NT_STATUS_IS_OK(cli_openx(cli
, "\\", O_RDONLY
, DENY_NONE
, &dnum
))) {
253 printf("open of \\ failed\n");
257 for (op
=OP_MIN
; op
<=OP_MAX
; op
++) {
258 printf("Scanning op=%d\n", op
);
259 for (level
= 0; level
<= 50; level
++) {
260 scan_trans2(cli
, op
, level
, fnum
, dnum
, fname
);
263 for (level
= 0x100; level
<= 0x130; level
++) {
264 scan_trans2(cli
, op
, level
, fnum
, dnum
, fname
);
267 for (level
= 1000; level
< 1050; level
++) {
268 scan_trans2(cli
, op
, level
, fnum
, dnum
, fname
);
272 torture_close_connection(cli
);
274 printf("trans2 scan finished\n");
281 /****************************************************************************
282 look for a partial hit
283 ****************************************************************************/
284 static void nttrans_check_hit(const char *format
, int op
, int level
, NTSTATUS status
)
286 if (NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL
) ||
287 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED
) ||
288 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED
) ||
289 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL
) ||
290 NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS
)) {
294 printf("possible %s hit op=%3d level=%5d status=%s\n",
295 format
, op
, level
, nt_errstr(status
));
299 /****************************************************************************
300 check for existence of a nttrans call
301 ****************************************************************************/
302 static NTSTATUS
try_nttrans(struct cli_state
*cli
,
304 uint8_t *param
, uint8_t *data
,
305 int32_t param_len
, uint32_t data_len
,
306 uint32_t *rparam_len
,
309 uint8_t *rparam
=NULL
, *rdata
=NULL
;
312 status
= cli_trans(talloc_tos(), cli
, SMBnttrans
,
313 NULL
, -1, /* name, fid */
315 NULL
, 0, 0, /* setup */
317 data
, data_len
, CLI_BUFFER_SIZE
,
318 NULL
, /* recv_flags2 */
319 NULL
, 0, NULL
, /* rsetup */
320 &rparam
, 0, rparam_len
,
321 &rdata
, 0, rdata_len
);
329 static NTSTATUS
try_nttrans_len(struct cli_state
*cli
,
332 uint8_t *param
, uint8_t *data
,
333 int param_len
, uint32_t *data_len
,
334 uint32_t *rparam_len
, uint32_t *rdata_len
)
336 NTSTATUS ret
=NT_STATUS_OK
;
338 ret
= try_nttrans(cli
, op
, param
, data
, param_len
,
339 DATA_SIZE
, rparam_len
, rdata_len
);
341 printf("op=%d level=%d ret=%s\n", op
, level
, nt_errstr(ret
));
343 if (!NT_STATUS_IS_OK(ret
)) return ret
;
346 while (*data_len
< DATA_SIZE
) {
347 ret
= try_nttrans(cli
, op
, param
, data
, param_len
,
348 *data_len
, rparam_len
, rdata_len
);
349 if (NT_STATUS_IS_OK(ret
)) break;
352 if (NT_STATUS_IS_OK(ret
)) {
353 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
354 format
, level
, *data_len
, *rparam_len
, *rdata_len
);
356 nttrans_check_hit(format
, op
, level
, ret
);
361 /****************************************************************************
362 check for existence of a nttrans call
363 ****************************************************************************/
364 static bool scan_nttrans(struct cli_state
*cli
, int op
, int level
,
365 int fnum
, int dnum
, const char *fname
)
367 uint32_t data_len
= 0;
368 uint32_t param_len
= 0;
369 uint32_t rparam_len
, rdata_len
;
370 uint8_t *param
= NULL
;
371 uint8_t data
[DATA_SIZE
];
373 const char *newfname
;
376 memset(data
, 0, sizeof(data
));
379 /* try with a info level only */
381 param
= talloc_array(talloc_tos(), uint8_t, 2);
382 if (param
== NULL
) return True
;
384 SSVAL(param
, 0, level
);
386 param_len
= talloc_get_size(param
);
387 status
= try_nttrans_len(cli
, "void", op
, level
, param
, data
, param_len
, &data_len
,
388 &rparam_len
, &rdata_len
);
389 if (NT_STATUS_IS_OK(status
)) return True
;
391 /* try with a file descriptor */
393 param
= talloc_array(talloc_tos(), uint8_t, 6);
394 if (param
== NULL
) return True
;
396 SSVAL(param
, 0, fnum
);
397 SSVAL(param
, 2, level
);
400 param_len
= talloc_get_size(param
);
401 status
= try_nttrans_len(cli
, "fnum", op
, level
, param
, data
, param_len
, &data_len
,
402 &rparam_len
, &rdata_len
);
403 if (NT_STATUS_IS_OK(status
)) return True
;
406 /* try with a notify style */
408 param
= talloc_array(talloc_tos(), uint8_t, 6);
409 if (param
== NULL
) return True
;
411 SSVAL(param
, 0, dnum
);
412 SSVAL(param
, 2, dnum
);
413 SSVAL(param
, 4, level
);
415 param_len
= talloc_get_size(param
);
416 status
= try_nttrans_len(cli
, "notify", op
, level
, param
, data
, param_len
, &data_len
,
417 &rparam_len
, &rdata_len
);
418 if (NT_STATUS_IS_OK(status
)) return True
;
420 /* try with a file name */
422 param
= talloc_array(talloc_tos(), uint8_t, 6);
423 if (param
== NULL
) return True
;
425 SSVAL(param
, 0, level
);
428 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
429 fname
, strlen(fname
)+1, NULL
);
430 if (param
== NULL
) return True
;
432 param_len
= talloc_get_size(param
);
433 status
= try_nttrans_len(cli
, "fname", op
, level
, param
, data
, param_len
, &data_len
,
434 &rparam_len
, &rdata_len
);
435 if (NT_STATUS_IS_OK(status
)) return True
;
437 /* try with a new file name */
438 newfname
= "\\newfile.dat";
440 param
= talloc_array(talloc_tos(), uint8_t, 6);
441 if (param
== NULL
) return True
;
443 SSVAL(param
, 0, level
);
446 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
447 newfname
, strlen(newfname
)+1, NULL
);
448 if (param
== NULL
) return True
;
450 param_len
= talloc_get_size(param
);
451 status
= try_nttrans_len(cli
, "newfile", op
, level
, param
, data
, param_len
, &data_len
,
452 &rparam_len
, &rdata_len
);
453 cli_unlink(cli
, newfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
454 cli_rmdir(cli
, newfname
);
455 if (NT_STATUS_IS_OK(status
)) return True
;
459 cli_mkdir(cli
, dname
);
461 param
= talloc_array(talloc_tos(), uint8_t, 2);
462 if (param
== NULL
) return True
;
464 SSVAL(param
, 0, level
);
465 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
466 dname
, strlen(dname
)+1, NULL
);
467 if (param
== NULL
) return True
;
469 param_len
= talloc_get_size(param
);
470 status
= try_nttrans_len(cli
, "dfs", op
, level
, param
, data
, param_len
, &data_len
,
471 &rparam_len
, &rdata_len
);
472 cli_rmdir(cli
, dname
);
473 if (NT_STATUS_IS_OK(status
)) return True
;
479 bool torture_nttrans_scan(int dummy
)
481 static struct cli_state
*cli
;
483 const char *fname
= "\\scanner.dat";
486 printf("starting nttrans scan test\n");
488 if (!torture_open_connection(&cli
, 0)) {
492 cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
,
494 cli_openx(cli
, "\\", O_RDONLY
, DENY_NONE
, &dnum
);
496 for (op
=OP_MIN
; op
<=OP_MAX
; op
++) {
497 printf("Scanning op=%d\n", op
);
498 for (level
= 0; level
<= 50; level
++) {
499 scan_nttrans(cli
, op
, level
, fnum
, dnum
, fname
);
502 for (level
= 0x100; level
<= 0x130; level
++) {
503 scan_nttrans(cli
, op
, level
, fnum
, dnum
, fname
);
506 for (level
= 1000; level
< 1050; level
++) {
507 scan_nttrans(cli
, op
, level
, fnum
, dnum
, fname
);
511 torture_close_connection(cli
);
513 printf("nttrans scan finished\n");