s3:auth: fix account unlock regression introduced with fix for bug #4347
[Samba/bb.git] / source3 / torture / scanner.c
blobe42e80abca46fe123e33af3897a2c8f6c8191121
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", aSYSTEM | aHIDDEN);
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 uint16_t fnum, dnum;
199 printf("starting trans2 scan test\n");
201 if (!torture_open_connection(&cli, 0)) {
202 return False;
205 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
206 DENY_NONE, &fnum))) {
207 printf("open of %s failed\n", fname);
208 return false;
210 if (!NT_STATUS_IS_OK(cli_open(cli, "\\", O_RDONLY, DENY_NONE, &dnum))) {
211 printf("open of \\ failed\n");
212 return false;
215 for (op=OP_MIN; op<=OP_MAX; op++) {
216 printf("Scanning op=%d\n", op);
217 for (level = 0; level <= 50; level++) {
218 scan_trans2(cli, op, level, fnum, dnum, fname);
221 for (level = 0x100; level <= 0x130; level++) {
222 scan_trans2(cli, op, level, fnum, dnum, fname);
225 for (level = 1000; level < 1050; level++) {
226 scan_trans2(cli, op, level, fnum, dnum, fname);
230 torture_close_connection(cli);
232 printf("trans2 scan finished\n");
233 return True;
239 /****************************************************************************
240 look for a partial hit
241 ****************************************************************************/
242 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
244 if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
245 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
246 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
247 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
248 NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
249 return;
251 #if VERBOSE
252 printf("possible %s hit op=%3d level=%5d status=%s\n",
253 format, op, level, nt_errstr(status));
254 #endif
257 /****************************************************************************
258 check for existance of a nttrans call
259 ****************************************************************************/
260 static NTSTATUS try_nttrans(struct cli_state *cli,
261 int op,
262 char *param, char *data,
263 int param_len, int data_len,
264 unsigned int *rparam_len, unsigned int *rdata_len)
266 char *rparam=NULL, *rdata=NULL;
268 if (!cli_send_nt_trans(cli, op,
270 NULL, 0, 0,
271 param, param_len, 2, /* param, length, max */
272 data, data_len, cli->max_xmit /* data, length, max */
273 )) {
274 return cli_nt_error(cli);
277 cli_receive_nt_trans(cli,
278 &rparam, rparam_len,
279 &rdata, rdata_len);
281 SAFE_FREE(rdata);
282 SAFE_FREE(rparam);
284 return cli_nt_error(cli);
288 static NTSTATUS try_nttrans_len(struct cli_state *cli,
289 const char *format,
290 int op, int level,
291 char *param, char *data,
292 int param_len, int *data_len,
293 unsigned int *rparam_len, unsigned int *rdata_len)
295 NTSTATUS ret=NT_STATUS_OK;
297 ret = try_nttrans(cli, op, param, data, param_len,
298 DATA_SIZE, rparam_len, rdata_len);
299 #if VERBOSE
300 printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
301 #endif
302 if (!NT_STATUS_IS_OK(ret)) return ret;
304 *data_len = 0;
305 while (*data_len < DATA_SIZE) {
306 ret = try_nttrans(cli, op, param, data, param_len,
307 *data_len, rparam_len, rdata_len);
308 if (NT_STATUS_IS_OK(ret)) break;
309 *data_len += 2;
311 if (NT_STATUS_IS_OK(ret)) {
312 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
313 format, level, *data_len, *rparam_len, *rdata_len);
314 } else {
315 nttrans_check_hit(format, op, level, ret);
317 return ret;
320 /****************************************************************************
321 check for existance of a nttrans call
322 ****************************************************************************/
323 static bool scan_nttrans(struct cli_state *cli, int op, int level,
324 int fnum, int dnum, const char *fname)
326 int data_len = 0;
327 int param_len = 0;
328 unsigned int rparam_len, rdata_len;
329 char param[PARAM_SIZE], data[DATA_SIZE];
330 NTSTATUS status;
332 memset(data, 0, sizeof(data));
333 data_len = 4;
335 /* try with a info level only */
336 param_len = 2;
337 SSVAL(param, 0, level);
338 status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len,
339 &rparam_len, &rdata_len);
340 if (NT_STATUS_IS_OK(status)) return True;
342 /* try with a file descriptor */
343 param_len = 6;
344 SSVAL(param, 0, fnum);
345 SSVAL(param, 2, level);
346 SSVAL(param, 4, 0);
347 status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len,
348 &rparam_len, &rdata_len);
349 if (NT_STATUS_IS_OK(status)) return True;
352 /* try with a notify style */
353 param_len = 6;
354 SSVAL(param, 0, dnum);
355 SSVAL(param, 2, dnum);
356 SSVAL(param, 4, level);
357 status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len,
358 &rparam_len, &rdata_len);
359 if (NT_STATUS_IS_OK(status)) return True;
361 /* try with a file name */
362 param_len = 6;
363 SSVAL(param, 0, level);
364 SSVAL(param, 2, 0);
365 SSVAL(param, 4, 0);
366 param_len += clistr_push(cli, &param[6], fname, -1, STR_TERMINATE);
368 status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len,
369 &rparam_len, &rdata_len);
370 if (NT_STATUS_IS_OK(status)) return True;
372 /* try with a new file name */
373 param_len = 6;
374 SSVAL(param, 0, level);
375 SSVAL(param, 2, 0);
376 SSVAL(param, 4, 0);
377 param_len += clistr_push(cli, &param[6], "\\newfile.dat", -1, STR_TERMINATE);
379 status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len,
380 &rparam_len, &rdata_len);
381 cli_unlink(cli, "\\newfile.dat", aSYSTEM | aHIDDEN);
382 cli_rmdir(cli, "\\newfile.dat");
383 if (NT_STATUS_IS_OK(status)) return True;
385 /* try dfs style */
386 cli_mkdir(cli, "\\testdir");
387 param_len = 2;
388 SSVAL(param, 0, level);
389 param_len += clistr_push(cli, &param[2], "\\testdir", -1, STR_TERMINATE);
391 status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len,
392 &rparam_len, &rdata_len);
393 cli_rmdir(cli, "\\testdir");
394 if (NT_STATUS_IS_OK(status)) return True;
396 return False;
400 bool torture_nttrans_scan(int dummy)
402 static struct cli_state *cli;
403 int op, level;
404 const char *fname = "\\scanner.dat";
405 uint16_t fnum, dnum;
407 printf("starting nttrans scan test\n");
409 if (!torture_open_connection(&cli, 0)) {
410 return False;
413 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
414 DENY_NONE, &fnum);
415 cli_open(cli, "\\", O_RDONLY, DENY_NONE, &dnum);
417 for (op=OP_MIN; op<=OP_MAX; op++) {
418 printf("Scanning op=%d\n", op);
419 for (level = 0; level <= 50; level++) {
420 scan_nttrans(cli, op, level, fnum, dnum, fname);
423 for (level = 0x100; level <= 0x130; level++) {
424 scan_nttrans(cli, op, level, fnum, dnum, fname);
427 for (level = 1000; level < 1050; level++) {
428 scan_nttrans(cli, op, level, fnum, dnum, fname);
432 torture_close_connection(cli);
434 printf("nttrans scan finished\n");
435 return True;