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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libcli/raw/libcliraw.h"
23 #include "librpc/gen_ndr/ndr_security.h"
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)) {
42 printf("possible %s hit op=%3d level=%5d status=%s\n",
43 format, op, level, nt_errstr(status));
47 /****************************************************************************
48 check for existance of a trans2 call
49 ****************************************************************************/
50 static NTSTATUS try_trans2(struct smbcli_state *cli,
52 uint8_t *param, uint8_t *data,
53 int param_len, int data_len,
54 int *rparam_len, int *rdata_len)
61 mem_ctx = talloc_init("try_trans2");
64 t2.in.max_data = smb_raw_max_trans_data(cli->tree, 64);
68 t2.in.setup_count = 1;
70 t2.in.params.data = param;
71 t2.in.params.length = param_len;
72 t2.in.data.data = data;
73 t2.in.data.length = data_len;
75 status = smb_raw_trans2(cli->tree, mem_ctx, &t2);
77 *rparam_len = t2.out.params.length;
78 *rdata_len = t2.out.data.length;
80 talloc_destroy(mem_ctx);
86 static NTSTATUS try_trans2_len(struct smbcli_state *cli,
89 uint8_t *param, uint8_t *data,
90 int param_len, int *data_len,
91 int *rparam_len, int *rdata_len)
93 NTSTATUS ret=NT_STATUS_OK;
95 ret = try_trans2(cli, op, param, data, param_len,
96 sizeof(pstring), rparam_len, rdata_len);
98 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
100 if (!NT_STATUS_IS_OK(ret)) return ret;
103 while (*data_len < sizeof(pstring)) {
104 ret = try_trans2(cli, op, param, data, param_len,
105 *data_len, rparam_len, rdata_len);
106 if (NT_STATUS_IS_OK(ret)) break;
109 if (NT_STATUS_IS_OK(ret)) {
110 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
111 format, level, *data_len, *rparam_len, *rdata_len);
113 trans2_check_hit(format, op, level, ret);
119 /****************************************************************************
120 check whether a trans2 opnum exists at all
121 ****************************************************************************/
122 static BOOL trans2_op_exists(struct smbcli_state *cli, int op)
126 int rparam_len, rdata_len;
127 uint8_t param[1024], data[1024];
128 NTSTATUS status1, status2;
130 memset(data, 0, sizeof(data));
133 /* try with a info level only */
134 param_len = sizeof(param);
135 data_len = sizeof(data);
137 memset(param, 0xFF, sizeof(param));
138 memset(data, 0xFF, sizeof(data));
140 status1 = try_trans2(cli, 0xFFFF, param, data, param_len, data_len,
141 &rparam_len, &rdata_len);
143 status2 = try_trans2(cli, op, param, data, param_len, data_len,
144 &rparam_len, &rdata_len);
146 if (NT_STATUS_EQUAL(status1, status2)) return False;
148 printf("Found op %d (status=%s)\n", op, nt_errstr(status2));
153 /****************************************************************************
154 check for existance of a trans2 call
155 ****************************************************************************/
156 static BOOL scan_trans2(struct smbcli_state *cli, int op, int level,
157 int fnum, int dnum, int qfnum, const char *fname)
161 int rparam_len, rdata_len;
162 uint8_t param[1024], data[1024];
165 memset(data, 0, sizeof(data));
168 /* try with a info level only */
170 SSVAL(param, 0, level);
171 status = try_trans2_len(cli, "void", 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 descriptor */
177 SSVAL(param, 0, fnum);
178 SSVAL(param, 2, level);
180 status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len,
181 &rparam_len, &rdata_len);
182 if (NT_STATUS_IS_OK(status)) return True;
184 /* try with a quota file descriptor */
186 SSVAL(param, 0, qfnum);
187 SSVAL(param, 2, level);
189 status = try_trans2_len(cli, "qfnum", op, level, param, data, param_len, &data_len,
190 &rparam_len, &rdata_len);
191 if (NT_STATUS_IS_OK(status)) return True;
193 /* try with a notify style */
195 SSVAL(param, 0, dnum);
196 SSVAL(param, 2, dnum);
197 SSVAL(param, 4, level);
198 status = try_trans2_len(cli, "notify", op, level, param, data, param_len, &data_len,
199 &rparam_len, &rdata_len);
200 if (NT_STATUS_IS_OK(status)) return True;
202 /* try with a file name */
204 SSVAL(param, 0, level);
207 param_len += push_string(¶m[6], fname, sizeof(pstring)-7, STR_TERMINATE|STR_UNICODE);
209 status = try_trans2_len(cli, "fname", op, level, param, data, param_len, &data_len,
210 &rparam_len, &rdata_len);
211 if (NT_STATUS_IS_OK(status)) return True;
213 /* try with a new file name */
215 SSVAL(param, 0, level);
218 param_len += push_string(¶m[6], "\\newfile.dat", sizeof(pstring)-7, STR_TERMINATE|STR_UNICODE);
220 status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len,
221 &rparam_len, &rdata_len);
222 smbcli_unlink(cli->tree, "\\newfile.dat");
223 smbcli_rmdir(cli->tree, "\\newfile.dat");
224 if (NT_STATUS_IS_OK(status)) return True;
227 smbcli_mkdir(cli->tree, "\\testdir");
229 SSVAL(param, 0, level);
230 param_len += push_string(¶m[2], "\\testdir", sizeof(pstring)-3, STR_TERMINATE|STR_UNICODE);
232 status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len,
233 &rparam_len, &rdata_len);
234 smbcli_rmdir(cli->tree, "\\testdir");
235 if (NT_STATUS_IS_OK(status)) return True;
241 BOOL torture_trans2_scan(void)
243 static struct smbcli_state *cli;
245 const char *fname = "\\scanner.dat";
246 int fnum, dnum, qfnum;
248 printf("starting trans2 scan test\n");
250 if (!torture_open_connection(&cli)) {
254 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
256 printf("file open failed - %s\n", smbcli_errstr(cli->tree));
258 dnum = smbcli_nt_create_full(cli->tree, "\\",
260 SEC_RIGHTS_FILE_READ,
261 FILE_ATTRIBUTE_NORMAL,
262 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE,
264 NTCREATEX_OPTIONS_DIRECTORY, 0);
266 printf("directory open failed - %s\n", smbcli_errstr(cli->tree));
268 qfnum = smbcli_nt_create_full(cli->tree, "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION",
269 NTCREATEX_FLAGS_EXTENDED,
270 SEC_RIGHTS_MAXIMUM_ALLOWED,
272 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
276 printf("quota open failed - %s\n", smbcli_errstr(cli->tree));
279 for (op=OP_MIN; op<=OP_MAX; op++) {
281 if (!trans2_op_exists(cli, op)) {
285 for (level = 0; level <= 50; level++) {
286 scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
289 for (level = 0x100; level <= 0x130; level++) {
290 scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
293 for (level = 1000; level < 1050; level++) {
294 scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
298 torture_close_connection(cli);
300 printf("trans2 scan finished\n");
307 /****************************************************************************
308 look for a partial hit
309 ****************************************************************************/
310 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
312 if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
313 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
314 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
315 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
316 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
320 printf("possible %s hit op=%3d level=%5d status=%s\n",
321 format, op, level, nt_errstr(status));
325 /****************************************************************************
326 check for existence of a nttrans call
327 ****************************************************************************/
328 static NTSTATUS try_nttrans(struct smbcli_state *cli,
330 uint8_t *param, uint8_t *data,
331 int param_len, int data_len,
332 int *rparam_len, int *rdata_len)
334 struct smb_nttrans parms;
335 DATA_BLOB ntparam_blob, ntdata_blob;
339 mem_ctx = talloc_init("try_nttrans");
341 ntparam_blob.length = param_len;
342 ntparam_blob.data = param;
343 ntdata_blob.length = data_len;
344 ntdata_blob.data = data;
346 parms.in.max_param = 64;
347 parms.in.max_data = smb_raw_max_trans_data(cli->tree, 64);
348 parms.in.max_setup = 0;
349 parms.in.setup_count = 0;
350 parms.in.function = op;
351 parms.in.params = ntparam_blob;
352 parms.in.data = ntdata_blob;
354 status = smb_raw_nttrans(cli->tree, mem_ctx, &parms);
356 if (NT_STATUS_IS_ERR(status)) {
357 DEBUG(1,("Failed to send NT_TRANS\n"));
358 talloc_destroy(mem_ctx);
361 *rparam_len = parms.out.params.length;
362 *rdata_len = parms.out.data.length;
364 talloc_destroy(mem_ctx);
370 static NTSTATUS try_nttrans_len(struct smbcli_state *cli,
373 uint8_t *param, uint8_t *data,
374 int param_len, int *data_len,
375 int *rparam_len, int *rdata_len)
377 NTSTATUS ret=NT_STATUS_OK;
379 ret = try_nttrans(cli, op, param, data, param_len,
380 sizeof(pstring), rparam_len, rdata_len);
382 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
384 if (!NT_STATUS_IS_OK(ret)) return ret;
387 while (*data_len < sizeof(pstring)) {
388 ret = try_nttrans(cli, op, param, data, param_len,
389 *data_len, rparam_len, rdata_len);
390 if (NT_STATUS_IS_OK(ret)) break;
393 if (NT_STATUS_IS_OK(ret)) {
394 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
395 format, level, *data_len, *rparam_len, *rdata_len);
397 nttrans_check_hit(format, op, level, ret);
402 /****************************************************************************
403 check for existance of a nttrans call
404 ****************************************************************************/
405 static BOOL scan_nttrans(struct smbcli_state *cli, int op, int level,
406 int fnum, int dnum, const char *fname)
410 int rparam_len, rdata_len;
411 uint8_t param[1024], data[1024];
414 memset(data, 0, sizeof(data));
417 /* try with a info level only */
419 SSVAL(param, 0, level);
420 status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len,
421 &rparam_len, &rdata_len);
422 if (NT_STATUS_IS_OK(status)) return True;
424 /* try with a file descriptor */
426 SSVAL(param, 0, fnum);
427 SSVAL(param, 2, level);
429 status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len,
430 &rparam_len, &rdata_len);
431 if (NT_STATUS_IS_OK(status)) return True;
434 /* try with a notify style */
436 SSVAL(param, 0, dnum);
437 SSVAL(param, 2, dnum);
438 SSVAL(param, 4, level);
439 status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len,
440 &rparam_len, &rdata_len);
441 if (NT_STATUS_IS_OK(status)) return True;
443 /* try with a file name */
445 SSVAL(param, 0, level);
448 param_len += push_string(¶m[6], fname, -1, STR_TERMINATE | STR_UNICODE);
450 status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len,
451 &rparam_len, &rdata_len);
452 if (NT_STATUS_IS_OK(status)) return True;
454 /* try with a new file name */
456 SSVAL(param, 0, level);
459 param_len += push_string(¶m[6], "\\newfile.dat", -1, STR_TERMINATE | STR_UNICODE);
461 status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len,
462 &rparam_len, &rdata_len);
463 smbcli_unlink(cli->tree, "\\newfile.dat");
464 smbcli_rmdir(cli->tree, "\\newfile.dat");
465 if (NT_STATUS_IS_OK(status)) return True;
468 smbcli_mkdir(cli->tree, "\\testdir");
470 SSVAL(param, 0, level);
471 param_len += push_string(¶m[2], "\\testdir", -1, STR_TERMINATE | STR_UNICODE);
473 status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len,
474 &rparam_len, &rdata_len);
475 smbcli_rmdir(cli->tree, "\\testdir");
476 if (NT_STATUS_IS_OK(status)) return True;
482 BOOL torture_nttrans_scan(void)
484 static struct smbcli_state *cli;
486 const char *fname = "\\scanner.dat";
489 printf("starting nttrans scan test\n");
491 if (!torture_open_connection(&cli)) {
495 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC,
497 dnum = smbcli_open(cli->tree, "\\", O_RDONLY, DENY_NONE);
499 for (op=OP_MIN; op<=OP_MAX; op++) {
500 printf("Scanning op=%d\n", op);
501 for (level = 0; level <= 50; level++) {
502 scan_nttrans(cli, op, level, fnum, dnum, fname);
505 for (level = 0x100; level <= 0x130; level++) {
506 scan_nttrans(cli, op, level, fnum, dnum, fname);
509 for (level = 1000; level < 1050; level++) {
510 scan_nttrans(cli, op, level, fnum, dnum, fname);
514 torture_close_connection(cli);
516 printf("nttrans scan finished\n");
521 /* scan for valid base SMB requests */
522 BOOL torture_smb_scan(void)
524 static struct smbcli_state *cli;
526 struct smbcli_request *req;
529 for (op=0x0;op<=0xFF;op++) {
530 if (op == SMBreadbraw) continue;
532 if (!torture_open_connection(&cli)) {
536 req = smbcli_request_setup(cli->tree, op, 0, 0);
538 if (!smbcli_request_send(req)) {
539 smbcli_request_destroy(req);
544 smbcli_transport_process(cli->transport);
545 if (req->state > SMBCLI_REQUEST_RECV) {
546 status = smbcli_request_simple_recv(req);
547 printf("op=0x%x status=%s\n", op, nt_errstr(status));
548 torture_close_connection(cli);
553 smbcli_transport_process(cli->transport);
554 if (req->state > SMBCLI_REQUEST_RECV) {
555 status = smbcli_request_simple_recv(req);
556 printf("op=0x%x status=%s\n", op, nt_errstr(status));
558 printf("op=0x%x no reply\n", op);
559 smbcli_request_destroy(req);
560 continue; /* don't attempt close! */
563 torture_close_connection(cli);
567 printf("smb scan finished\n");