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