s3-utils/net_rpc_printer.c: print more info on write error
[Samba/gebeck_regimport.git] / source3 / torture / scanner.c
blob5edd52d56791c2ad7bd204ad7c21cd808775b3a3
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"
21 #include "system/filesys.h"
22 #include "torture/proto.h"
23 #include "libsmb/libsmb.h"
25 #define VERBOSE 0
26 #define OP_MIN 0
27 #define OP_MAX 20
29 #define DATA_SIZE 1024
30 #define PARAM_SIZE 1024
32 /****************************************************************************
33 look for a partial hit
34 ****************************************************************************/
35 static void trans2_check_hit(const char *format, int op, int level, NTSTATUS status)
37 if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
38 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
39 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
40 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
41 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
42 return;
44 #if VERBOSE
45 printf("possible %s hit op=%3d level=%5d status=%s\n",
46 format, op, level, nt_errstr(status));
47 #endif
50 /****************************************************************************
51 check for existance of a trans2 call
52 ****************************************************************************/
53 static NTSTATUS try_trans2(struct cli_state *cli,
54 int op,
55 uint8_t *param, uint8_t *data,
56 uint32_t param_len, uint32_t data_len,
57 uint32_t *rparam_len, uint32_t *rdata_len)
59 uint16_t setup[1];
60 uint8_t *rparam=NULL, *rdata=NULL;
61 NTSTATUS status;
63 SSVAL(setup+0, 0, op);
65 status = cli_trans(talloc_tos(), cli, SMBtrans2,
66 NULL, -1, /* name, fid */
67 op, 0,
68 NULL, 0, 0, /* setup */
69 param, param_len, 2,
70 data, data_len, cli->max_xmit,
71 NULL, /* recv_flags2 */
72 NULL, 0, NULL, /* rsetup */
73 &rparam, 0, rparam_len,
74 &rdata, 0, rdata_len);
76 TALLOC_FREE(rdata);
77 TALLOC_FREE(rparam);
79 return status;
83 static NTSTATUS try_trans2_len(struct cli_state *cli,
84 const char *format,
85 int op, int level,
86 uint8_t *param, uint8_t *data,
87 uint32_t param_len, uint32_t *data_len,
88 uint32_t *rparam_len, uint32_t *rdata_len)
90 NTSTATUS ret=NT_STATUS_OK;
92 ret = try_trans2(cli, op, param, data, param_len,
93 DATA_SIZE, rparam_len, rdata_len);
94 #if VERBOSE
95 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
96 #endif
97 if (!NT_STATUS_IS_OK(ret)) return ret;
99 *data_len = 0;
100 while (*data_len < DATA_SIZE) {
101 ret = try_trans2(cli, op, param, data, param_len,
102 *data_len, rparam_len, rdata_len);
103 if (NT_STATUS_IS_OK(ret)) break;
104 *data_len += 2;
106 if (NT_STATUS_IS_OK(ret)) {
107 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
108 format, level, *data_len, *rparam_len, *rdata_len);
109 } else {
110 trans2_check_hit(format, op, level, ret);
112 return ret;
115 /****************************************************************************
116 check for existance of a trans2 call
117 ****************************************************************************/
118 static bool scan_trans2(struct cli_state *cli, int op, int level,
119 int fnum, int dnum, const char *fname)
121 uint32_t data_len = 0;
122 uint32_t param_len = 0;
123 uint32_t rparam_len, rdata_len;
124 uint8_t *param = NULL;
125 uint8_t data[DATA_SIZE];
126 const char *newfname;
127 const char *dname;
128 NTSTATUS status;
130 memset(data, 0, sizeof(data));
131 data_len = 4;
133 /* try with a info level only */
134 TALLOC_FREE(param);
135 param = talloc_array(talloc_tos(), uint8_t, 2);
136 if (param == NULL) return True;
138 SSVAL(param, 0, level);
140 param_len = talloc_get_size(param);
141 status = try_trans2_len(cli, "void", op, level, param, data, param_len, &data_len,
142 &rparam_len, &rdata_len);
143 if (NT_STATUS_IS_OK(status)) return True;
145 /* try with a file descriptor */
146 TALLOC_FREE(param);
147 param = talloc_array(talloc_tos(), uint8_t, 6);
148 if (param == NULL) return True;
150 SSVAL(param, 0, fnum);
151 SSVAL(param, 2, level);
152 SSVAL(param, 4, 0);
154 param_len = talloc_get_size(param);
155 status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len,
156 &rparam_len, &rdata_len);
157 if (NT_STATUS_IS_OK(status)) return True;
160 /* try with a notify style */
161 TALLOC_FREE(param);
162 param = talloc_array(talloc_tos(), uint8_t, 6);
163 if (param == NULL) return True;
165 SSVAL(param, 0, dnum);
166 SSVAL(param, 2, dnum);
167 SSVAL(param, 4, level);
169 param_len = talloc_get_size(param);
170 status = try_trans2_len(cli, "notify", op, level, param, data, param_len, &data_len,
171 &rparam_len, &rdata_len);
172 if (NT_STATUS_IS_OK(status)) return True;
174 /* try with a file name */
175 TALLOC_FREE(param);
176 param = talloc_array(talloc_tos(), uint8_t, 6);
177 if (param == NULL) return True;
179 SSVAL(param, 0, level);
180 SSVAL(param, 2, 0);
181 SSVAL(param, 4, 0);
182 param = trans2_bytes_push_str(param, cli_ucs2(cli),
183 fname, strlen(fname)+1, NULL);
184 if (param == NULL) return True;
186 param_len = talloc_get_size(param);
187 status = try_trans2_len(cli, "fname", op, level, param, data, param_len, &data_len,
188 &rparam_len, &rdata_len);
189 if (NT_STATUS_IS_OK(status)) return True;
191 /* try with a new file name */
192 newfname = "\\newfile.dat";
193 TALLOC_FREE(param);
194 param = talloc_array(talloc_tos(), uint8_t, 6);
195 if (param == NULL) return True;
197 SSVAL(param, 0, level);
198 SSVAL(param, 2, 0);
199 SSVAL(param, 4, 0);
200 param = trans2_bytes_push_str(param, cli_ucs2(cli),
201 newfname, strlen(newfname)+1, NULL);
202 if (param == NULL) return True;
204 param_len = talloc_get_size(param);
205 status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len,
206 &rparam_len, &rdata_len);
207 cli_unlink(cli, newfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
208 cli_rmdir(cli, newfname);
209 if (NT_STATUS_IS_OK(status)) return True;
211 /* try dfs style */
212 dname = "\\testdir";
213 cli_mkdir(cli, dname);
214 TALLOC_FREE(param);
215 param = talloc_array(talloc_tos(), uint8_t, 2);
216 if (param == NULL) return True;
218 SSVAL(param, 0, level);
219 param = trans2_bytes_push_str(param, cli_ucs2(cli),
220 dname, strlen(dname)+1, NULL);
221 if (param == NULL) return True;
223 param_len = talloc_get_size(param);
224 status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len,
225 &rparam_len, &rdata_len);
226 cli_rmdir(cli, dname);
227 if (NT_STATUS_IS_OK(status)) return True;
229 return False;
233 bool torture_trans2_scan(int dummy)
235 static struct cli_state *cli;
236 int op, level;
237 const char *fname = "\\scanner.dat";
238 uint16_t fnum, dnum;
240 printf("starting trans2 scan test\n");
242 if (!torture_open_connection(&cli, 0)) {
243 return False;
246 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
247 DENY_NONE, &fnum))) {
248 printf("open of %s failed\n", fname);
249 return false;
251 if (!NT_STATUS_IS_OK(cli_open(cli, "\\", O_RDONLY, DENY_NONE, &dnum))) {
252 printf("open of \\ failed\n");
253 return false;
256 for (op=OP_MIN; op<=OP_MAX; op++) {
257 printf("Scanning op=%d\n", op);
258 for (level = 0; level <= 50; level++) {
259 scan_trans2(cli, op, level, fnum, dnum, fname);
262 for (level = 0x100; level <= 0x130; level++) {
263 scan_trans2(cli, op, level, fnum, dnum, fname);
266 for (level = 1000; level < 1050; level++) {
267 scan_trans2(cli, op, level, fnum, dnum, fname);
271 torture_close_connection(cli);
273 printf("trans2 scan finished\n");
274 return True;
280 /****************************************************************************
281 look for a partial hit
282 ****************************************************************************/
283 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
285 if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
286 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
287 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
288 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
289 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
290 return;
292 #if VERBOSE
293 printf("possible %s hit op=%3d level=%5d status=%s\n",
294 format, op, level, nt_errstr(status));
295 #endif
298 /****************************************************************************
299 check for existance of a nttrans call
300 ****************************************************************************/
301 static NTSTATUS try_nttrans(struct cli_state *cli,
302 int op,
303 uint8_t *param, uint8_t *data,
304 int32_t param_len, uint32_t data_len,
305 uint32_t *rparam_len,
306 uint32_t *rdata_len)
308 uint8_t *rparam=NULL, *rdata=NULL;
309 NTSTATUS status;
311 status = cli_trans(talloc_tos(), cli, SMBnttrans,
312 NULL, -1, /* name, fid */
313 op, 0,
314 NULL, 0, 0, /* setup */
315 param, param_len, 2,
316 data, data_len, cli->max_xmit,
317 NULL, /* recv_flags2 */
318 NULL, 0, NULL, /* rsetup */
319 &rparam, 0, rparam_len,
320 &rdata, 0, rdata_len);
321 SAFE_FREE(rdata);
322 SAFE_FREE(rparam);
324 return status;
328 static NTSTATUS try_nttrans_len(struct cli_state *cli,
329 const char *format,
330 int op, int level,
331 uint8_t *param, uint8_t *data,
332 int param_len, uint32_t *data_len,
333 uint32_t *rparam_len, uint32_t *rdata_len)
335 NTSTATUS ret=NT_STATUS_OK;
337 ret = try_nttrans(cli, op, param, data, param_len,
338 DATA_SIZE, rparam_len, rdata_len);
339 #if VERBOSE
340 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
341 #endif
342 if (!NT_STATUS_IS_OK(ret)) return ret;
344 *data_len = 0;
345 while (*data_len < DATA_SIZE) {
346 ret = try_nttrans(cli, op, param, data, param_len,
347 *data_len, rparam_len, rdata_len);
348 if (NT_STATUS_IS_OK(ret)) break;
349 *data_len += 2;
351 if (NT_STATUS_IS_OK(ret)) {
352 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
353 format, level, *data_len, *rparam_len, *rdata_len);
354 } else {
355 nttrans_check_hit(format, op, level, ret);
357 return ret;
360 /****************************************************************************
361 check for existance of a nttrans call
362 ****************************************************************************/
363 static bool scan_nttrans(struct cli_state *cli, int op, int level,
364 int fnum, int dnum, const char *fname)
366 uint32_t data_len = 0;
367 uint32_t param_len = 0;
368 uint32_t rparam_len, rdata_len;
369 uint8_t *param = NULL;
370 uint8_t data[DATA_SIZE];
371 NTSTATUS status;
372 const char *newfname;
373 const char *dname;
375 memset(data, 0, sizeof(data));
376 data_len = 4;
378 /* try with a info level only */
379 TALLOC_FREE(param);
380 param = talloc_array(talloc_tos(), uint8_t, 2);
381 if (param == NULL) return True;
383 SSVAL(param, 0, level);
385 param_len = talloc_get_size(param);
386 status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len,
387 &rparam_len, &rdata_len);
388 if (NT_STATUS_IS_OK(status)) return True;
390 /* try with a file descriptor */
391 TALLOC_FREE(param);
392 param = talloc_array(talloc_tos(), uint8_t, 6);
393 if (param == NULL) return True;
395 SSVAL(param, 0, fnum);
396 SSVAL(param, 2, level);
397 SSVAL(param, 4, 0);
399 param_len = talloc_get_size(param);
400 status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len,
401 &rparam_len, &rdata_len);
402 if (NT_STATUS_IS_OK(status)) return True;
405 /* try with a notify style */
406 TALLOC_FREE(param);
407 param = talloc_array(talloc_tos(), uint8_t, 6);
408 if (param == NULL) return True;
410 SSVAL(param, 0, dnum);
411 SSVAL(param, 2, dnum);
412 SSVAL(param, 4, level);
414 param_len = talloc_get_size(param);
415 status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len,
416 &rparam_len, &rdata_len);
417 if (NT_STATUS_IS_OK(status)) return True;
419 /* try with a file name */
420 TALLOC_FREE(param);
421 param = talloc_array(talloc_tos(), uint8_t, 6);
422 if (param == NULL) return True;
424 SSVAL(param, 0, level);
425 SSVAL(param, 2, 0);
426 SSVAL(param, 4, 0);
427 param = trans2_bytes_push_str(param, cli_ucs2(cli),
428 fname, strlen(fname)+1, NULL);
429 if (param == NULL) return True;
431 param_len = talloc_get_size(param);
432 status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len,
433 &rparam_len, &rdata_len);
434 if (NT_STATUS_IS_OK(status)) return True;
436 /* try with a new file name */
437 newfname = "\\newfile.dat";
438 TALLOC_FREE(param);
439 param = talloc_array(talloc_tos(), uint8_t, 6);
440 if (param == NULL) return True;
442 SSVAL(param, 0, level);
443 SSVAL(param, 2, 0);
444 SSVAL(param, 4, 0);
445 param = trans2_bytes_push_str(param, cli_ucs2(cli),
446 newfname, strlen(newfname)+1, NULL);
447 if (param == NULL) return True;
449 param_len = talloc_get_size(param);
450 status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len,
451 &rparam_len, &rdata_len);
452 cli_unlink(cli, newfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
453 cli_rmdir(cli, newfname);
454 if (NT_STATUS_IS_OK(status)) return True;
456 /* try dfs style */
457 dname = "\\testdir";
458 cli_mkdir(cli, dname);
459 TALLOC_FREE(param);
460 param = talloc_array(talloc_tos(), uint8_t, 2);
461 if (param == NULL) return True;
463 SSVAL(param, 0, level);
464 param = trans2_bytes_push_str(param, cli_ucs2(cli),
465 dname, strlen(dname)+1, NULL);
466 if (param == NULL) return True;
468 param_len = talloc_get_size(param);
469 status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len,
470 &rparam_len, &rdata_len);
471 cli_rmdir(cli, dname);
472 if (NT_STATUS_IS_OK(status)) return True;
474 return False;
478 bool torture_nttrans_scan(int dummy)
480 static struct cli_state *cli;
481 int op, level;
482 const char *fname = "\\scanner.dat";
483 uint16_t fnum, dnum;
485 printf("starting nttrans scan test\n");
487 if (!torture_open_connection(&cli, 0)) {
488 return False;
491 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
492 DENY_NONE, &fnum);
493 cli_open(cli, "\\", O_RDONLY, DENY_NONE, &dnum);
495 for (op=OP_MIN; op<=OP_MAX; op++) {
496 printf("Scanning op=%d\n", op);
497 for (level = 0; level <= 50; level++) {
498 scan_nttrans(cli, op, level, fnum, dnum, fname);
501 for (level = 0x100; level <= 0x130; level++) {
502 scan_nttrans(cli, op, level, fnum, dnum, fname);
505 for (level = 1000; level < 1050; level++) {
506 scan_nttrans(cli, op, level, fnum, dnum, fname);
510 torture_close_connection(cli);
512 printf("nttrans scan finished\n");
513 return True;