This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[sfrench/samba-autobuild/.git] / source / torture / scanner.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester - scanning functions
4    Copyright (C) Andrew Tridgell 2001
5    
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.
10    
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.
15    
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.
19 */
20
21 #define NO_SYSLOG
22
23 #include "includes.h"
24
25 #define VERBOSE 0
26 #define OP_MIN 0
27 #define OP_MAX 20
28
29 /****************************************************************************
30 look for a partial hit
31 ****************************************************************************/
32 static void trans2_check_hit(char *format, int op, int level, NTSTATUS status)
33 {
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;
40         }
41 #if VERBOSE
42         printf("possible %s hit op=%3d level=%5d status=%s\n",
43                format, op, level, nt_errstr(status));
44 #endif
45 }
46
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                          int *rparam_len, int *rdata_len)
55 {
56         uint16 setup = op;
57         char *rparam=NULL, *rdata=NULL;
58
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);
67         }
68
69         cli_receive_trans(cli, SMBtrans2,
70                            &rparam, rparam_len,
71                            &rdata, rdata_len);
72
73         SAFE_FREE(rdata);
74         SAFE_FREE(rparam);
75
76         return cli_nt_error(cli);
77 }
78
79
80 static NTSTATUS try_trans2_len(struct cli_state *cli, 
81                              char *format,
82                              int op, int level,
83                              char *param, char *data,
84                              int param_len, int *data_len,
85                              int *rparam_len, int *rdata_len)
86 {
87         NTSTATUS ret=NT_STATUS_OK;
88
89         ret = try_trans2(cli, op, param, data, param_len,
90                          sizeof(pstring), 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;
95
96         *data_len = 0;
97         while (*data_len < sizeof(pstring)) {
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;
102         }
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);
108         }
109         return ret;
110 }
111
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, char *fname)
117 {
118         int data_len = 0;
119         int param_len = 0;
120         int rparam_len, rdata_len;
121         pstring param, data;
122         NTSTATUS status;
123
124         memset(data, 0, sizeof(data));
125         data_len = 4;
126
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;
133
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;
142
143
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;
152
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);
159
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;
163
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);
170
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");
174         cli_rmdir(cli, "\\newfile.dat");
175         if (NT_STATUS_IS_OK(status)) return True;
176
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);
182
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;
187
188         return False;
189 }
190
191
192 BOOL torture_trans2_scan(int dummy)
193 {
194         static struct cli_state cli;
195         int op, level;
196         char *fname = "\\scanner.dat";
197         int fnum, dnum;
198
199         printf("starting trans2 scan test\n");
200
201         if (!torture_open_connection(&cli)) {
202                 return False;
203         }
204
205         fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, 
206                          DENY_NONE);
207         dnum = cli_open(&cli, "\\", O_RDONLY, DENY_NONE);
208
209         for (op=OP_MIN; op<=OP_MAX; op++) {
210                 printf("Scanning op=%d\n", op);
211                 for (level = 0; level <= 50; level++) {
212                         scan_trans2(&cli, op, level, fnum, dnum, fname);
213                 }
214
215                 for (level = 0x100; level <= 0x130; level++) {
216                         scan_trans2(&cli, op, level, fnum, dnum, fname);
217                 }
218
219                 for (level = 1000; level < 1050; level++) {
220                         scan_trans2(&cli, op, level, fnum, dnum, fname);
221                 }
222         }
223
224         torture_close_connection(&cli);
225
226         printf("trans2 scan finished\n");
227         return True;
228 }
229
230
231
232
233 /****************************************************************************
234 look for a partial hit
235 ****************************************************************************/
236 static void nttrans_check_hit(char *format, int op, int level, NTSTATUS status)
237 {
238         if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
239             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
240             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
241             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
242             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
243                 return;
244         }
245 #if VERBOSE
246                 printf("possible %s hit op=%3d level=%5d status=%s\n",
247                        format, op, level, nt_errstr(status));
248 #endif
249 }
250
251 /****************************************************************************
252 check for existance of a nttrans call
253 ****************************************************************************/
254 static NTSTATUS try_nttrans(struct cli_state *cli, 
255                          int op,
256                          char *param, char *data,
257                          int param_len, int data_len,
258                          int *rparam_len, int *rdata_len)
259 {
260         char *rparam=NULL, *rdata=NULL;
261
262         if (!cli_send_nt_trans(cli, op, 
263                                0,   
264                                NULL, 0, 0,
265                                param, param_len, 2,            /* param, length, max */
266                                data, data_len, cli->max_xmit   /* data, length, max */
267                            )) {
268                 return cli_nt_error(cli);
269         }
270
271         cli_receive_nt_trans(cli,
272                              &rparam, rparam_len,
273                              &rdata, rdata_len);
274
275         SAFE_FREE(rdata);
276         SAFE_FREE(rparam);
277
278         return cli_nt_error(cli);
279 }
280
281
282 static NTSTATUS try_nttrans_len(struct cli_state *cli, 
283                              char *format,
284                              int op, int level,
285                              char *param, char *data,
286                              int param_len, int *data_len,
287                              int *rparam_len, int *rdata_len)
288 {
289         NTSTATUS ret=NT_STATUS_OK;
290
291         ret = try_nttrans(cli, op, param, data, param_len,
292                          sizeof(pstring), rparam_len, rdata_len);
293 #if VERBOSE 
294         printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
295 #endif
296         if (!NT_STATUS_IS_OK(ret)) return ret;
297
298         *data_len = 0;
299         while (*data_len < sizeof(pstring)) {
300                 ret = try_nttrans(cli, op, param, data, param_len,
301                                  *data_len, rparam_len, rdata_len);
302                 if (NT_STATUS_IS_OK(ret)) break;
303                 *data_len += 2;
304         }
305         if (NT_STATUS_IS_OK(ret)) {
306                 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
307                        format, level, *data_len, *rparam_len, *rdata_len);
308         } else {
309                 nttrans_check_hit(format, op, level, ret);
310         }
311         return ret;
312 }
313
314 /****************************************************************************
315 check for existance of a nttrans call
316 ****************************************************************************/
317 static BOOL scan_nttrans(struct cli_state *cli, int op, int level, 
318                         int fnum, int dnum, char *fname)
319 {
320         int data_len = 0;
321         int param_len = 0;
322         int rparam_len, rdata_len;
323         pstring param, data;
324         NTSTATUS status;
325
326         memset(data, 0, sizeof(data));
327         data_len = 4;
328
329         /* try with a info level only */
330         param_len = 2;
331         SSVAL(param, 0, level);
332         status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len, 
333                             &rparam_len, &rdata_len);
334         if (NT_STATUS_IS_OK(status)) return True;
335
336         /* try with a file descriptor */
337         param_len = 6;
338         SSVAL(param, 0, fnum);
339         SSVAL(param, 2, level);
340         SSVAL(param, 4, 0);
341         status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
342                                 &rparam_len, &rdata_len);
343         if (NT_STATUS_IS_OK(status)) return True;
344
345
346         /* try with a notify style */
347         param_len = 6;
348         SSVAL(param, 0, dnum);
349         SSVAL(param, 2, dnum);
350         SSVAL(param, 4, level);
351         status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len, 
352                                 &rparam_len, &rdata_len);
353         if (NT_STATUS_IS_OK(status)) return True;
354
355         /* try with a file name */
356         param_len = 6;
357         SSVAL(param, 0, level);
358         SSVAL(param, 2, 0);
359         SSVAL(param, 4, 0);
360         param_len += clistr_push(cli, &param[6], fname, -1, STR_TERMINATE);
361
362         status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len, 
363                                 &rparam_len, &rdata_len);
364         if (NT_STATUS_IS_OK(status)) return True;
365
366         /* try with a new file name */
367         param_len = 6;
368         SSVAL(param, 0, level);
369         SSVAL(param, 2, 0);
370         SSVAL(param, 4, 0);
371         param_len += clistr_push(cli, &param[6], "\\newfile.dat", -1, STR_TERMINATE);
372
373         status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
374                                 &rparam_len, &rdata_len);
375         cli_unlink(cli, "\\newfile.dat");
376         cli_rmdir(cli, "\\newfile.dat");
377         if (NT_STATUS_IS_OK(status)) return True;
378
379         /* try dfs style  */
380         cli_mkdir(cli, "\\testdir");
381         param_len = 2;
382         SSVAL(param, 0, level);
383         param_len += clistr_push(cli, &param[2], "\\testdir", -1, STR_TERMINATE);
384
385         status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
386                                 &rparam_len, &rdata_len);
387         cli_rmdir(cli, "\\testdir");
388         if (NT_STATUS_IS_OK(status)) return True;
389
390         return False;
391 }
392
393
394 BOOL torture_nttrans_scan(int dummy)
395 {
396         static struct cli_state cli;
397         int op, level;
398         char *fname = "\\scanner.dat";
399         int fnum, dnum;
400
401         printf("starting nttrans scan test\n");
402
403         if (!torture_open_connection(&cli)) {
404                 return False;
405         }
406
407         fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, 
408                          DENY_NONE);
409         dnum = cli_open(&cli, "\\", O_RDONLY, DENY_NONE);
410
411         for (op=OP_MIN; op<=OP_MAX; op++) {
412                 printf("Scanning op=%d\n", op);
413                 for (level = 0; level <= 50; level++) {
414                         scan_nttrans(&cli, op, level, fnum, dnum, fname);
415                 }
416
417                 for (level = 0x100; level <= 0x130; level++) {
418                         scan_nttrans(&cli, op, level, fnum, dnum, fname);
419                 }
420
421                 for (level = 1000; level < 1050; level++) {
422                         scan_nttrans(&cli, op, level, fnum, dnum, fname);
423                 }
424         }
425
426         torture_close_connection(&cli);
427
428         printf("nttrans scan finished\n");
429         return True;
430 }