r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[tprouty/samba.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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21
22 #define VERBOSE 0
23 #define OP_MIN 0
24 #define OP_MAX 20
25
26 /****************************************************************************
27 look for a partial hit
28 ****************************************************************************/
29 static void trans2_check_hit(const char *format, int op, int level, NTSTATUS status)
30 {
31         if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
32             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
33             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
34             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
35             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
36                 return;
37         }
38 #if VERBOSE
39         printf("possible %s hit op=%3d level=%5d status=%s\n",
40                format, op, level, nt_errstr(status));
41 #endif
42 }
43
44 /****************************************************************************
45 check for existance of a trans2 call
46 ****************************************************************************/
47 static NTSTATUS try_trans2(struct cli_state *cli, 
48                          int op,
49                          char *param, char *data,
50                          int param_len, int data_len,
51                          unsigned int *rparam_len, unsigned int *rdata_len)
52 {
53         uint16 setup = op;
54         char *rparam=NULL, *rdata=NULL;
55
56         if (!cli_send_trans(cli, SMBtrans2, 
57                             NULL,                           /* name */
58                             -1, 0,                          /* fid, flags */
59                             &setup, 1, 0,                   /* setup, length, max */
60                             param, param_len, 2,            /* param, length, max */
61                             data, data_len, cli->max_xmit   /* data, length, max */
62                            )) {
63                 return cli_nt_error(cli);
64         }
65
66         cli_receive_trans(cli, SMBtrans2,
67                            &rparam, rparam_len,
68                            &rdata, rdata_len);
69
70         SAFE_FREE(rdata);
71         SAFE_FREE(rparam);
72
73         return cli_nt_error(cli);
74 }
75
76
77 static NTSTATUS try_trans2_len(struct cli_state *cli, 
78                              const char *format,
79                              int op, int level,
80                              char *param, char *data,
81                              int param_len, int *data_len,
82                              unsigned int *rparam_len, unsigned int *rdata_len)
83 {
84         NTSTATUS ret=NT_STATUS_OK;
85
86         ret = try_trans2(cli, op, param, data, param_len,
87                          sizeof(pstring), rparam_len, rdata_len);
88 #if VERBOSE 
89         printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
90 #endif
91         if (!NT_STATUS_IS_OK(ret)) return ret;
92
93         *data_len = 0;
94         while (*data_len < sizeof(pstring)) {
95                 ret = try_trans2(cli, op, param, data, param_len,
96                                  *data_len, rparam_len, rdata_len);
97                 if (NT_STATUS_IS_OK(ret)) break;
98                 *data_len += 2;
99         }
100         if (NT_STATUS_IS_OK(ret)) {
101                 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
102                        format, level, *data_len, *rparam_len, *rdata_len);
103         } else {
104                 trans2_check_hit(format, op, level, ret);
105         }
106         return ret;
107 }
108
109 /****************************************************************************
110 check for existance of a trans2 call
111 ****************************************************************************/
112 static BOOL scan_trans2(struct cli_state *cli, int op, int level, 
113                         int fnum, int dnum, const char *fname)
114 {
115         int data_len = 0;
116         int param_len = 0;
117         unsigned int rparam_len, rdata_len;
118         pstring param, data;
119         NTSTATUS status;
120
121         memset(data, 0, sizeof(data));
122         data_len = 4;
123
124         /* try with a info level only */
125         param_len = 2;
126         SSVAL(param, 0, level);
127         status = try_trans2_len(cli, "void", op, level, param, data, param_len, &data_len, 
128                             &rparam_len, &rdata_len);
129         if (NT_STATUS_IS_OK(status)) return True;
130
131         /* try with a file descriptor */
132         param_len = 6;
133         SSVAL(param, 0, fnum);
134         SSVAL(param, 2, level);
135         SSVAL(param, 4, 0);
136         status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
137                                 &rparam_len, &rdata_len);
138         if (NT_STATUS_IS_OK(status)) return True;
139
140
141         /* try with a notify style */
142         param_len = 6;
143         SSVAL(param, 0, dnum);
144         SSVAL(param, 2, dnum);
145         SSVAL(param, 4, level);
146         status = try_trans2_len(cli, "notify", op, level, param, data, param_len, &data_len, 
147                                 &rparam_len, &rdata_len);
148         if (NT_STATUS_IS_OK(status)) return True;
149
150         /* try with a file name */
151         param_len = 6;
152         SSVAL(param, 0, level);
153         SSVAL(param, 2, 0);
154         SSVAL(param, 4, 0);
155         param_len += clistr_push(cli, &param[6], fname, -1, STR_TERMINATE);
156
157         status = try_trans2_len(cli, "fname", op, level, param, data, param_len, &data_len, 
158                                 &rparam_len, &rdata_len);
159         if (NT_STATUS_IS_OK(status)) return True;
160
161         /* try with a new file name */
162         param_len = 6;
163         SSVAL(param, 0, level);
164         SSVAL(param, 2, 0);
165         SSVAL(param, 4, 0);
166         param_len += clistr_push(cli, &param[6], "\\newfile.dat", -1, STR_TERMINATE);
167
168         status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
169                                 &rparam_len, &rdata_len);
170         cli_unlink(cli, "\\newfile.dat");
171         cli_rmdir(cli, "\\newfile.dat");
172         if (NT_STATUS_IS_OK(status)) return True;
173
174         /* try dfs style  */
175         cli_mkdir(cli, "\\testdir");
176         param_len = 2;
177         SSVAL(param, 0, level);
178         param_len += clistr_push(cli, &param[2], "\\testdir", -1, STR_TERMINATE);
179
180         status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
181                                 &rparam_len, &rdata_len);
182         cli_rmdir(cli, "\\testdir");
183         if (NT_STATUS_IS_OK(status)) return True;
184
185         return False;
186 }
187
188
189 BOOL torture_trans2_scan(int dummy)
190 {
191         static struct cli_state *cli;
192         int op, level;
193         const char *fname = "\\scanner.dat";
194         int fnum, dnum;
195
196         printf("starting trans2 scan test\n");
197
198         if (!torture_open_connection(&cli, 0)) {
199                 return False;
200         }
201
202         fnum = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, 
203                          DENY_NONE);
204         dnum = cli_open(cli, "\\", O_RDONLY, DENY_NONE);
205
206         for (op=OP_MIN; op<=OP_MAX; op++) {
207                 printf("Scanning op=%d\n", op);
208                 for (level = 0; level <= 50; level++) {
209                         scan_trans2(cli, op, level, fnum, dnum, fname);
210                 }
211
212                 for (level = 0x100; level <= 0x130; level++) {
213                         scan_trans2(cli, op, level, fnum, dnum, fname);
214                 }
215
216                 for (level = 1000; level < 1050; level++) {
217                         scan_trans2(cli, op, level, fnum, dnum, fname);
218                 }
219         }
220
221         torture_close_connection(cli);
222
223         printf("trans2 scan finished\n");
224         return True;
225 }
226
227
228
229
230 /****************************************************************************
231 look for a partial hit
232 ****************************************************************************/
233 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
234 {
235         if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
236             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
237             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
238             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
239             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
240                 return;
241         }
242 #if VERBOSE
243                 printf("possible %s hit op=%3d level=%5d status=%s\n",
244                        format, op, level, nt_errstr(status));
245 #endif
246 }
247
248 /****************************************************************************
249 check for existance of a nttrans call
250 ****************************************************************************/
251 static NTSTATUS try_nttrans(struct cli_state *cli, 
252                          int op,
253                          char *param, char *data,
254                          int param_len, int data_len,
255                          unsigned int *rparam_len, unsigned int *rdata_len)
256 {
257         char *rparam=NULL, *rdata=NULL;
258
259         if (!cli_send_nt_trans(cli, op, 
260                                0,   
261                                NULL, 0, 0,
262                                param, param_len, 2,            /* param, length, max */
263                                data, data_len, cli->max_xmit   /* data, length, max */
264                            )) {
265                 return cli_nt_error(cli);
266         }
267
268         cli_receive_nt_trans(cli,
269                              &rparam, rparam_len,
270                              &rdata, rdata_len);
271
272         SAFE_FREE(rdata);
273         SAFE_FREE(rparam);
274
275         return cli_nt_error(cli);
276 }
277
278
279 static NTSTATUS try_nttrans_len(struct cli_state *cli, 
280                              const char *format,
281                              int op, int level,
282                              char *param, char *data,
283                              int param_len, int *data_len,
284                              unsigned int *rparam_len, unsigned int *rdata_len)
285 {
286         NTSTATUS ret=NT_STATUS_OK;
287
288         ret = try_nttrans(cli, op, param, data, param_len,
289                          sizeof(pstring), rparam_len, rdata_len);
290 #if VERBOSE 
291         printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
292 #endif
293         if (!NT_STATUS_IS_OK(ret)) return ret;
294
295         *data_len = 0;
296         while (*data_len < sizeof(pstring)) {
297                 ret = try_nttrans(cli, op, param, data, param_len,
298                                  *data_len, rparam_len, rdata_len);
299                 if (NT_STATUS_IS_OK(ret)) break;
300                 *data_len += 2;
301         }
302         if (NT_STATUS_IS_OK(ret)) {
303                 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
304                        format, level, *data_len, *rparam_len, *rdata_len);
305         } else {
306                 nttrans_check_hit(format, op, level, ret);
307         }
308         return ret;
309 }
310
311 /****************************************************************************
312 check for existance of a nttrans call
313 ****************************************************************************/
314 static BOOL scan_nttrans(struct cli_state *cli, int op, int level, 
315                         int fnum, int dnum, const char *fname)
316 {
317         int data_len = 0;
318         int param_len = 0;
319         unsigned int rparam_len, rdata_len;
320         pstring param, data;
321         NTSTATUS status;
322
323         memset(data, 0, sizeof(data));
324         data_len = 4;
325
326         /* try with a info level only */
327         param_len = 2;
328         SSVAL(param, 0, level);
329         status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len, 
330                             &rparam_len, &rdata_len);
331         if (NT_STATUS_IS_OK(status)) return True;
332
333         /* try with a file descriptor */
334         param_len = 6;
335         SSVAL(param, 0, fnum);
336         SSVAL(param, 2, level);
337         SSVAL(param, 4, 0);
338         status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
339                                 &rparam_len, &rdata_len);
340         if (NT_STATUS_IS_OK(status)) return True;
341
342
343         /* try with a notify style */
344         param_len = 6;
345         SSVAL(param, 0, dnum);
346         SSVAL(param, 2, dnum);
347         SSVAL(param, 4, level);
348         status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len, 
349                                 &rparam_len, &rdata_len);
350         if (NT_STATUS_IS_OK(status)) return True;
351
352         /* try with a file name */
353         param_len = 6;
354         SSVAL(param, 0, level);
355         SSVAL(param, 2, 0);
356         SSVAL(param, 4, 0);
357         param_len += clistr_push(cli, &param[6], fname, -1, STR_TERMINATE);
358
359         status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len, 
360                                 &rparam_len, &rdata_len);
361         if (NT_STATUS_IS_OK(status)) return True;
362
363         /* try with a new file name */
364         param_len = 6;
365         SSVAL(param, 0, level);
366         SSVAL(param, 2, 0);
367         SSVAL(param, 4, 0);
368         param_len += clistr_push(cli, &param[6], "\\newfile.dat", -1, STR_TERMINATE);
369
370         status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
371                                 &rparam_len, &rdata_len);
372         cli_unlink(cli, "\\newfile.dat");
373         cli_rmdir(cli, "\\newfile.dat");
374         if (NT_STATUS_IS_OK(status)) return True;
375
376         /* try dfs style  */
377         cli_mkdir(cli, "\\testdir");
378         param_len = 2;
379         SSVAL(param, 0, level);
380         param_len += clistr_push(cli, &param[2], "\\testdir", -1, STR_TERMINATE);
381
382         status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
383                                 &rparam_len, &rdata_len);
384         cli_rmdir(cli, "\\testdir");
385         if (NT_STATUS_IS_OK(status)) return True;
386
387         return False;
388 }
389
390
391 BOOL torture_nttrans_scan(int dummy)
392 {
393         static struct cli_state *cli;
394         int op, level;
395         const char *fname = "\\scanner.dat";
396         int fnum, dnum;
397
398         printf("starting nttrans scan test\n");
399
400         if (!torture_open_connection(&cli, 0)) {
401                 return False;
402         }
403
404         fnum = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, 
405                          DENY_NONE);
406         dnum = cli_open(cli, "\\", O_RDONLY, DENY_NONE);
407
408         for (op=OP_MIN; op<=OP_MAX; op++) {
409                 printf("Scanning op=%d\n", op);
410                 for (level = 0; level <= 50; level++) {
411                         scan_nttrans(cli, op, level, fnum, dnum, fname);
412                 }
413
414                 for (level = 0x100; level <= 0x130; level++) {
415                         scan_nttrans(cli, op, level, fnum, dnum, fname);
416                 }
417
418                 for (level = 1000; level < 1050; level++) {
419                         scan_nttrans(cli, op, level, fnum, dnum, fname);
420                 }
421         }
422
423         torture_close_connection(cli);
424
425         printf("nttrans scan finished\n");
426         return True;
427 }