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 "system/filesys.h"
24 #include "librpc/gen_ndr/ndr_security.h"
31 /****************************************************************************
32 look for a partial hit
33 ****************************************************************************/
34 static void trans2_check_hit(const char *format, int op, int level, NTSTATUS status)
36 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL) ||
37 NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) ||
38 NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
39 NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) ||
40 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
44 printf("possible %s hit op=%3d level=%5d status=%s\n",
45 format, op, level, nt_errstr(status));
49 /****************************************************************************
50 check for existance of a trans2 call
51 ****************************************************************************/
52 static NTSTATUS try_trans2(struct smbcli_state *cli,
54 uint8_t *param, uint8_t *data,
55 int param_len, int data_len,
56 int *rparam_len, int *rdata_len)
63 mem_ctx = talloc_init("try_trans2");
66 t2.in.max_data = smb_raw_max_trans_data(cli->tree, 64);
70 t2.in.setup_count = 1;
72 t2.in.params.data = param;
73 t2.in.params.length = param_len;
74 t2.in.data.data = data;
75 t2.in.data.length = data_len;
77 status = smb_raw_trans2(cli->tree, mem_ctx, &t2);
79 *rparam_len = t2.out.params.length;
80 *rdata_len = t2.out.data.length;
88 static NTSTATUS try_trans2_len(struct smbcli_state *cli,
91 uint8_t *param, uint8_t *data,
92 int param_len, int *data_len,
93 int *rparam_len, int *rdata_len)
95 NTSTATUS ret=NT_STATUS_OK;
97 ret = try_trans2(cli, op, param, data, param_len,
98 sizeof(pstring), rparam_len, rdata_len);
100 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
102 if (!NT_STATUS_IS_OK(ret)) return ret;
105 while (*data_len < sizeof(pstring)) {
106 ret = try_trans2(cli, op, param, data, param_len,
107 *data_len, rparam_len, rdata_len);
108 if (NT_STATUS_IS_OK(ret)) break;
111 if (NT_STATUS_IS_OK(ret)) {
112 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
113 format, level, *data_len, *rparam_len, *rdata_len);
115 trans2_check_hit(format, op, level, ret);
121 /****************************************************************************
122 check whether a trans2 opnum exists at all
123 ****************************************************************************/
124 static BOOL trans2_op_exists(struct smbcli_state *cli, int op)
128 int rparam_len, rdata_len;
129 uint8_t param[1024], data[1024];
130 NTSTATUS status1, status2;
132 memset(data, 0, sizeof(data));
135 /* try with a info level only */
136 param_len = sizeof(param);
137 data_len = sizeof(data);
139 memset(param, 0xFF, sizeof(param));
140 memset(data, 0xFF, sizeof(data));
142 status1 = try_trans2(cli, 0xFFFF, param, data, param_len, data_len,
143 &rparam_len, &rdata_len);
145 status2 = try_trans2(cli, op, param, data, param_len, data_len,
146 &rparam_len, &rdata_len);
148 if (NT_STATUS_EQUAL(status1, status2)) return False;
150 printf("Found op %d (status=%s)\n", op, nt_errstr(status2));
155 /****************************************************************************
156 check for existance of a trans2 call
157 ****************************************************************************/
158 static BOOL scan_trans2(struct smbcli_state *cli, int op, int level,
159 int fnum, int dnum, int qfnum, const char *fname)
163 int rparam_len, rdata_len;
164 uint8_t param[1024], data[1024];
167 memset(data, 0, sizeof(data));
170 /* try with a info level only */
172 SSVAL(param, 0, level);
173 status = try_trans2_len(cli, "void", op, level, param, data, param_len, &data_len,
174 &rparam_len, &rdata_len);
175 if (NT_STATUS_IS_OK(status)) return True;
177 /* try with a file descriptor */
179 SSVAL(param, 0, fnum);
180 SSVAL(param, 2, level);
182 status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len,
183 &rparam_len, &rdata_len);
184 if (NT_STATUS_IS_OK(status)) return True;
186 /* try with a quota file descriptor */
188 SSVAL(param, 0, qfnum);
189 SSVAL(param, 2, level);
191 status = try_trans2_len(cli, "qfnum", op, level, param, data, param_len, &data_len,
192 &rparam_len, &rdata_len);
193 if (NT_STATUS_IS_OK(status)) return True;
195 /* try with a notify style */
197 SSVAL(param, 0, dnum);
198 SSVAL(param, 2, dnum);
199 SSVAL(param, 4, level);
200 status = try_trans2_len(cli, "notify", op, level, param, data, param_len, &data_len,
201 &rparam_len, &rdata_len);
202 if (NT_STATUS_IS_OK(status)) return True;
204 /* try with a file name */
206 SSVAL(param, 0, level);
209 param_len += push_string(¶m[6], fname, sizeof(pstring)-7, STR_TERMINATE|STR_UNICODE);
211 status = try_trans2_len(cli, "fname", op, level, param, data, param_len, &data_len,
212 &rparam_len, &rdata_len);
213 if (NT_STATUS_IS_OK(status)) return True;
215 /* try with a new file name */
217 SSVAL(param, 0, level);
220 param_len += push_string(¶m[6], "\\newfile.dat", sizeof(pstring)-7, STR_TERMINATE|STR_UNICODE);
222 status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len,
223 &rparam_len, &rdata_len);
224 smbcli_unlink(cli->tree, "\\newfile.dat");
225 smbcli_rmdir(cli->tree, "\\newfile.dat");
226 if (NT_STATUS_IS_OK(status)) return True;
229 smbcli_mkdir(cli->tree, "\\testdir");
231 SSVAL(param, 0, level);
232 param_len += push_string(¶m[2], "\\testdir", sizeof(pstring)-3, STR_TERMINATE|STR_UNICODE);
234 status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len,
235 &rparam_len, &rdata_len);
236 smbcli_rmdir(cli->tree, "\\testdir");
237 if (NT_STATUS_IS_OK(status)) return True;
243 BOOL torture_trans2_scan(void)
245 static struct smbcli_state *cli;
247 const char *fname = "\\scanner.dat";
248 int fnum, dnum, qfnum;
250 printf("starting trans2 scan test\n");
252 if (!torture_open_connection(&cli)) {
256 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
258 printf("file open failed - %s\n", smbcli_errstr(cli->tree));
260 dnum = smbcli_nt_create_full(cli->tree, "\\",
262 SEC_RIGHTS_FILE_READ,
263 FILE_ATTRIBUTE_NORMAL,
264 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE,
266 NTCREATEX_OPTIONS_DIRECTORY, 0);
268 printf("directory open failed - %s\n", smbcli_errstr(cli->tree));
270 qfnum = smbcli_nt_create_full(cli->tree, "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION",
271 NTCREATEX_FLAGS_EXTENDED,
272 SEC_FLAG_MAXIMUM_ALLOWED,
274 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
278 printf("quota open failed - %s\n", smbcli_errstr(cli->tree));
281 for (op=OP_MIN; op<=OP_MAX; op++) {
283 if (!trans2_op_exists(cli, op)) {
287 for (level = 0; level <= 50; level++) {
288 scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
291 for (level = 0x100; level <= 0x130; level++) {
292 scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
295 for (level = 1000; level < 1050; level++) {
296 scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
300 torture_close_connection(cli);
302 printf("trans2 scan finished\n");
309 /****************************************************************************
310 look for a partial hit
311 ****************************************************************************/
312 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
314 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL) ||
315 NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) ||
316 NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
317 NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) ||
318 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
322 printf("possible %s hit op=%3d level=%5d status=%s\n",
323 format, op, level, nt_errstr(status));
327 /****************************************************************************
328 check for existence of a nttrans call
329 ****************************************************************************/
330 static NTSTATUS try_nttrans(struct smbcli_state *cli,
332 uint8_t *param, uint8_t *data,
333 int param_len, int data_len,
334 int *rparam_len, int *rdata_len)
336 struct smb_nttrans parms;
337 DATA_BLOB ntparam_blob, ntdata_blob;
341 mem_ctx = talloc_init("try_nttrans");
343 ntparam_blob.length = param_len;
344 ntparam_blob.data = param;
345 ntdata_blob.length = data_len;
346 ntdata_blob.data = data;
348 parms.in.max_param = 64;
349 parms.in.max_data = smb_raw_max_trans_data(cli->tree, 64);
350 parms.in.max_setup = 0;
351 parms.in.setup_count = 0;
352 parms.in.function = op;
353 parms.in.params = ntparam_blob;
354 parms.in.data = ntdata_blob;
356 status = smb_raw_nttrans(cli->tree, mem_ctx, &parms);
358 if (NT_STATUS_IS_ERR(status)) {
359 DEBUG(1,("Failed to send NT_TRANS\n"));
360 talloc_free(mem_ctx);
363 *rparam_len = parms.out.params.length;
364 *rdata_len = parms.out.data.length;
366 talloc_free(mem_ctx);
372 static NTSTATUS try_nttrans_len(struct smbcli_state *cli,
375 uint8_t *param, uint8_t *data,
376 int param_len, int *data_len,
377 int *rparam_len, int *rdata_len)
379 NTSTATUS ret=NT_STATUS_OK;
381 ret = try_nttrans(cli, op, param, data, param_len,
382 sizeof(pstring), rparam_len, rdata_len);
384 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
386 if (!NT_STATUS_IS_OK(ret)) return ret;
389 while (*data_len < sizeof(pstring)) {
390 ret = try_nttrans(cli, op, param, data, param_len,
391 *data_len, rparam_len, rdata_len);
392 if (NT_STATUS_IS_OK(ret)) break;
395 if (NT_STATUS_IS_OK(ret)) {
396 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
397 format, level, *data_len, *rparam_len, *rdata_len);
399 nttrans_check_hit(format, op, level, ret);
404 /****************************************************************************
405 check for existance of a nttrans call
406 ****************************************************************************/
407 static BOOL scan_nttrans(struct smbcli_state *cli, int op, int level,
408 int fnum, int dnum, const char *fname)
412 int rparam_len, rdata_len;
413 uint8_t param[1024], data[1024];
416 memset(data, 0, sizeof(data));
419 /* try with a info level only */
421 SSVAL(param, 0, level);
422 status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len,
423 &rparam_len, &rdata_len);
424 if (NT_STATUS_IS_OK(status)) return True;
426 /* try with a file descriptor */
428 SSVAL(param, 0, fnum);
429 SSVAL(param, 2, level);
431 status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len,
432 &rparam_len, &rdata_len);
433 if (NT_STATUS_IS_OK(status)) return True;
436 /* try with a notify style */
438 SSVAL(param, 0, dnum);
439 SSVAL(param, 2, dnum);
440 SSVAL(param, 4, level);
441 status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len,
442 &rparam_len, &rdata_len);
443 if (NT_STATUS_IS_OK(status)) return True;
445 /* try with a file name */
447 SSVAL(param, 0, level);
450 param_len += push_string(¶m[6], fname, -1, STR_TERMINATE | STR_UNICODE);
452 status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len,
453 &rparam_len, &rdata_len);
454 if (NT_STATUS_IS_OK(status)) return True;
456 /* try with a new file name */
458 SSVAL(param, 0, level);
461 param_len += push_string(¶m[6], "\\newfile.dat", -1, STR_TERMINATE | STR_UNICODE);
463 status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len,
464 &rparam_len, &rdata_len);
465 smbcli_unlink(cli->tree, "\\newfile.dat");
466 smbcli_rmdir(cli->tree, "\\newfile.dat");
467 if (NT_STATUS_IS_OK(status)) return True;
470 smbcli_mkdir(cli->tree, "\\testdir");
472 SSVAL(param, 0, level);
473 param_len += push_string(¶m[2], "\\testdir", -1, STR_TERMINATE | STR_UNICODE);
475 status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len,
476 &rparam_len, &rdata_len);
477 smbcli_rmdir(cli->tree, "\\testdir");
478 if (NT_STATUS_IS_OK(status)) return True;
484 BOOL torture_nttrans_scan(void)
486 static struct smbcli_state *cli;
488 const char *fname = "\\scanner.dat";
491 printf("starting nttrans scan test\n");
493 if (!torture_open_connection(&cli)) {
497 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC,
499 dnum = smbcli_open(cli->tree, "\\", O_RDONLY, DENY_NONE);
501 for (op=OP_MIN; op<=OP_MAX; op++) {
502 printf("Scanning op=%d\n", op);
503 for (level = 0; level <= 50; level++) {
504 scan_nttrans(cli, op, level, fnum, dnum, fname);
507 for (level = 0x100; level <= 0x130; level++) {
508 scan_nttrans(cli, op, level, fnum, dnum, fname);
511 for (level = 1000; level < 1050; level++) {
512 scan_nttrans(cli, op, level, fnum, dnum, fname);
516 torture_close_connection(cli);
518 printf("nttrans scan finished\n");
523 /* scan for valid base SMB requests */
524 BOOL torture_smb_scan(void)
526 static struct smbcli_state *cli;
528 struct smbcli_request *req;
531 for (op=0x0;op<=0xFF;op++) {
532 if (op == SMBreadbraw) continue;
534 if (!torture_open_connection(&cli)) {
538 req = smbcli_request_setup(cli->tree, op, 0, 0);
540 if (!smbcli_request_send(req)) {
541 smbcli_request_destroy(req);
546 smbcli_transport_process(cli->transport);
547 if (req->state > SMBCLI_REQUEST_RECV) {
548 status = smbcli_request_simple_recv(req);
549 printf("op=0x%x status=%s\n", op, nt_errstr(status));
550 torture_close_connection(cli);
555 smbcli_transport_process(cli->transport);
556 if (req->state > SMBCLI_REQUEST_RECV) {
557 status = smbcli_request_simple_recv(req);
558 printf("op=0x%x status=%s\n", op, nt_errstr(status));
560 printf("op=0x%x no reply\n", op);
561 smbcli_request_destroy(req);
562 continue; /* don't attempt close! */
565 torture_close_connection(cli);
569 printf("smb scan finished\n");