r3971: fix compiler warnings
[bbaumbach/samba-autobuild/.git] / source4 / torture / basic / 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 #include "includes.h"
22 #include "libcli/raw/libcliraw.h"
23
24 #define VERBOSE 0
25 #define OP_MIN 0
26 #define OP_MAX 100
27
28 /****************************************************************************
29 look for a partial hit
30 ****************************************************************************/
31 static void trans2_check_hit(const char *format, int op, int level, NTSTATUS status)
32 {
33         if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
34             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
35             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
36             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
37             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
38                 return;
39         }
40 #if VERBOSE
41         printf("possible %s hit op=%3d level=%5d status=%s\n",
42                format, op, level, nt_errstr(status));
43 #endif
44 }
45
46 /****************************************************************************
47 check for existance of a trans2 call
48 ****************************************************************************/
49 static NTSTATUS try_trans2(struct smbcli_state *cli, 
50                            int op,
51                            uint8_t *param, uint8_t *data,
52                            int param_len, int data_len,
53                            int *rparam_len, int *rdata_len)
54 {
55         NTSTATUS status;
56         struct smb_trans2 t2;
57         uint16_t setup = op;
58         TALLOC_CTX *mem_ctx;
59
60         mem_ctx = talloc_init("try_trans2");
61
62         t2.in.max_param = 64;
63         t2.in.max_data = smb_raw_max_trans_data(cli->tree, 64);
64         t2.in.max_setup = 10;
65         t2.in.flags = 0;
66         t2.in.timeout = 0;
67         t2.in.setup_count = 1;
68         t2.in.setup = &setup;
69         t2.in.params.data = param;
70         t2.in.params.length = param_len;
71         t2.in.data.data = data;
72         t2.in.data.length = data_len;
73
74         status = smb_raw_trans2(cli->tree, mem_ctx, &t2);
75
76         *rparam_len = t2.out.params.length;
77         *rdata_len = t2.out.data.length;
78
79         talloc_destroy(mem_ctx);
80         
81         return status;
82 }
83
84
85 static NTSTATUS try_trans2_len(struct smbcli_state *cli, 
86                              const char *format,
87                              int op, int level,
88                              uint8_t *param, uint8_t *data,
89                              int param_len, int *data_len,
90                              int *rparam_len, int *rdata_len)
91 {
92         NTSTATUS ret=NT_STATUS_OK;
93
94         ret = try_trans2(cli, op, param, data, param_len,
95                          sizeof(pstring), rparam_len, rdata_len);
96 #if VERBOSE 
97         printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
98 #endif
99         if (!NT_STATUS_IS_OK(ret)) return ret;
100
101         *data_len = 0;
102         while (*data_len < sizeof(pstring)) {
103                 ret = try_trans2(cli, op, param, data, param_len,
104                                  *data_len, rparam_len, rdata_len);
105                 if (NT_STATUS_IS_OK(ret)) break;
106                 *data_len += 2;
107         }
108         if (NT_STATUS_IS_OK(ret)) {
109                 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
110                        format, level, *data_len, *rparam_len, *rdata_len);
111         } else {
112                 trans2_check_hit(format, op, level, ret);
113         }
114         return ret;
115 }
116
117
118 /****************************************************************************
119 check whether a trans2 opnum exists at all
120 ****************************************************************************/
121 static BOOL trans2_op_exists(struct smbcli_state *cli, int op)
122 {
123         int data_len = 0;
124         int param_len = 0;
125         int rparam_len, rdata_len;
126         uint8_t param[1024], data[1024];
127         NTSTATUS status1, status2;
128
129         memset(data, 0, sizeof(data));
130         data_len = 4;
131
132         /* try with a info level only */
133         param_len = sizeof(param);
134         data_len = sizeof(data);
135
136         memset(param, 0xFF, sizeof(param));
137         memset(data, 0xFF, sizeof(data));
138         
139         status1 = try_trans2(cli, 0xFFFF, param, data, param_len, data_len, 
140                              &rparam_len, &rdata_len);
141
142         status2 = try_trans2(cli, op, param, data, param_len, data_len, 
143                              &rparam_len, &rdata_len);
144
145         if (NT_STATUS_EQUAL(status1, status2)) return False;
146
147         printf("Found op %d (status=%s)\n", op, nt_errstr(status2));
148
149         return True;
150 }
151
152 /****************************************************************************
153 check for existance of a trans2 call
154 ****************************************************************************/
155 static BOOL scan_trans2(struct smbcli_state *cli, int op, int level, 
156                         int fnum, int dnum, int qfnum, const char *fname)
157 {
158         int data_len = 0;
159         int param_len = 0;
160         int rparam_len, rdata_len;
161         uint8_t param[1024], data[1024];
162         NTSTATUS status;
163
164         memset(data, 0, sizeof(data));
165         data_len = 4;
166
167         /* try with a info level only */
168         param_len = 2;
169         SSVAL(param, 0, level);
170         status = try_trans2_len(cli, "void", op, level, param, data, param_len, &data_len, 
171                             &rparam_len, &rdata_len);
172         if (NT_STATUS_IS_OK(status)) return True;
173
174         /* try with a file descriptor */
175         param_len = 6;
176         SSVAL(param, 0, fnum);
177         SSVAL(param, 2, level);
178         SSVAL(param, 4, 0);
179         status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
180                                 &rparam_len, &rdata_len);
181         if (NT_STATUS_IS_OK(status)) return True;
182
183         /* try with a quota file descriptor */
184         param_len = 6;
185         SSVAL(param, 0, qfnum);
186         SSVAL(param, 2, level);
187         SSVAL(param, 4, 0);
188         status = try_trans2_len(cli, "qfnum", op, level, param, data, param_len, &data_len, 
189                                 &rparam_len, &rdata_len);
190         if (NT_STATUS_IS_OK(status)) return True;
191
192         /* try with a notify style */
193         param_len = 6;
194         SSVAL(param, 0, dnum);
195         SSVAL(param, 2, dnum);
196         SSVAL(param, 4, level);
197         status = try_trans2_len(cli, "notify", op, level, param, data, param_len, &data_len, 
198                                 &rparam_len, &rdata_len);
199         if (NT_STATUS_IS_OK(status)) return True;
200
201         /* try with a file name */
202         param_len = 6;
203         SSVAL(param, 0, level);
204         SSVAL(param, 2, 0);
205         SSVAL(param, 4, 0);
206         param_len += push_string(&param[6], fname, sizeof(pstring)-7, STR_TERMINATE|STR_UNICODE);
207
208         status = try_trans2_len(cli, "fname", op, level, param, data, param_len, &data_len, 
209                                 &rparam_len, &rdata_len);
210         if (NT_STATUS_IS_OK(status)) return True;
211
212         /* try with a new file name */
213         param_len = 6;
214         SSVAL(param, 0, level);
215         SSVAL(param, 2, 0);
216         SSVAL(param, 4, 0);
217         param_len += push_string(&param[6], "\\newfile.dat", sizeof(pstring)-7, STR_TERMINATE|STR_UNICODE);
218
219         status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
220                                 &rparam_len, &rdata_len);
221         smbcli_unlink(cli->tree, "\\newfile.dat");
222         smbcli_rmdir(cli->tree, "\\newfile.dat");
223         if (NT_STATUS_IS_OK(status)) return True;
224
225         /* try dfs style  */
226         smbcli_mkdir(cli->tree, "\\testdir");
227         param_len = 2;
228         SSVAL(param, 0, level);
229         param_len += push_string(&param[2], "\\testdir", sizeof(pstring)-3, STR_TERMINATE|STR_UNICODE);
230
231         status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
232                                 &rparam_len, &rdata_len);
233         smbcli_rmdir(cli->tree, "\\testdir");
234         if (NT_STATUS_IS_OK(status)) return True;
235
236         return False;
237 }
238
239
240 BOOL torture_trans2_scan(void)
241 {
242         static struct smbcli_state *cli;
243         int op, level;
244         const char *fname = "\\scanner.dat";
245         int fnum, dnum, qfnum;
246
247         printf("starting trans2 scan test\n");
248
249         if (!torture_open_connection(&cli)) {
250                 return False;
251         }
252
253         fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
254         if (fnum == -1) {
255                 printf("file open failed - %s\n", smbcli_errstr(cli->tree));
256         }
257         dnum = smbcli_nt_create_full(cli->tree, "\\", 
258                                   0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
259                                   NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE, 
260                                   NTCREATEX_DISP_OPEN, 
261                                   NTCREATEX_OPTIONS_DIRECTORY, 0);
262         if (dnum == -1) {
263                 printf("directory open failed - %s\n", smbcli_errstr(cli->tree));
264         }
265         qfnum = smbcli_nt_create_full(cli->tree, "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION", 
266                                    NTCREATEX_FLAGS_EXTENDED, 
267                                    SEC_RIGHTS_MAXIMUM_ALLOWED, 
268                                    0,
269                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
270                                    NTCREATEX_DISP_OPEN, 
271                                    0, 0);
272         if (qfnum == -1) {
273                 printf("quota open failed - %s\n", smbcli_errstr(cli->tree));
274         }
275
276         for (op=OP_MIN; op<=OP_MAX; op++) {
277
278                 if (!trans2_op_exists(cli, op)) {
279                         continue;
280                 }
281
282                 for (level = 0; level <= 50; level++) {
283                         scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
284                 }
285
286                 for (level = 0x100; level <= 0x130; level++) {
287                         scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
288                 }
289
290                 for (level = 1000; level < 1050; level++) {
291                         scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
292                 }
293         }
294
295         torture_close_connection(cli);
296
297         printf("trans2 scan finished\n");
298         return True;
299 }
300
301
302
303
304 /****************************************************************************
305 look for a partial hit
306 ****************************************************************************/
307 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
308 {
309         if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
310             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
311             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
312             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
313             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
314                 return;
315         }
316 #if VERBOSE
317                 printf("possible %s hit op=%3d level=%5d status=%s\n",
318                        format, op, level, nt_errstr(status));
319 #endif
320 }
321
322 /****************************************************************************
323 check for existence of a nttrans call
324 ****************************************************************************/
325 static NTSTATUS try_nttrans(struct smbcli_state *cli, 
326                             int op,
327                             uint8_t *param, uint8_t *data,
328                             int param_len, int data_len,
329                             int *rparam_len, int *rdata_len)
330 {
331         struct smb_nttrans parms;
332         DATA_BLOB ntparam_blob, ntdata_blob;
333         TALLOC_CTX *mem_ctx;
334         NTSTATUS status;
335
336         mem_ctx = talloc_init("try_nttrans");
337
338         ntparam_blob.length = param_len;
339         ntparam_blob.data = param;
340         ntdata_blob.length = data_len;
341         ntdata_blob.data = data;
342
343         parms.in.max_param = 64;
344         parms.in.max_data = smb_raw_max_trans_data(cli->tree, 64);
345         parms.in.max_setup = 0;
346         parms.in.setup_count = 0;
347         parms.in.function = op;
348         parms.in.params = ntparam_blob;
349         parms.in.data = ntdata_blob;
350         
351         status = smb_raw_nttrans(cli->tree, mem_ctx, &parms);
352         
353         if (NT_STATUS_IS_ERR(status)) {
354                 DEBUG(1,("Failed to send NT_TRANS\n"));
355                 talloc_destroy(mem_ctx);
356                 return status;
357         }
358         *rparam_len = parms.out.params.length;
359         *rdata_len = parms.out.data.length;
360
361         talloc_destroy(mem_ctx);
362
363         return status;
364 }
365
366
367 static NTSTATUS try_nttrans_len(struct smbcli_state *cli, 
368                              const char *format,
369                              int op, int level,
370                              uint8_t *param, uint8_t *data,
371                              int param_len, int *data_len,
372                              int *rparam_len, int *rdata_len)
373 {
374         NTSTATUS ret=NT_STATUS_OK;
375
376         ret = try_nttrans(cli, op, param, data, param_len,
377                          sizeof(pstring), rparam_len, rdata_len);
378 #if VERBOSE 
379         printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
380 #endif
381         if (!NT_STATUS_IS_OK(ret)) return ret;
382
383         *data_len = 0;
384         while (*data_len < sizeof(pstring)) {
385                 ret = try_nttrans(cli, op, param, data, param_len,
386                                  *data_len, rparam_len, rdata_len);
387                 if (NT_STATUS_IS_OK(ret)) break;
388                 *data_len += 2;
389         }
390         if (NT_STATUS_IS_OK(ret)) {
391                 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
392                        format, level, *data_len, *rparam_len, *rdata_len);
393         } else {
394                 nttrans_check_hit(format, op, level, ret);
395         }
396         return ret;
397 }
398
399 /****************************************************************************
400 check for existance of a nttrans call
401 ****************************************************************************/
402 static BOOL scan_nttrans(struct smbcli_state *cli, int op, int level, 
403                         int fnum, int dnum, const char *fname)
404 {
405         int data_len = 0;
406         int param_len = 0;
407         int rparam_len, rdata_len;
408         uint8_t param[1024], data[1024];
409         NTSTATUS status;
410
411         memset(data, 0, sizeof(data));
412         data_len = 4;
413
414         /* try with a info level only */
415         param_len = 2;
416         SSVAL(param, 0, level);
417         status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len, 
418                             &rparam_len, &rdata_len);
419         if (NT_STATUS_IS_OK(status)) return True;
420
421         /* try with a file descriptor */
422         param_len = 6;
423         SSVAL(param, 0, fnum);
424         SSVAL(param, 2, level);
425         SSVAL(param, 4, 0);
426         status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
427                                 &rparam_len, &rdata_len);
428         if (NT_STATUS_IS_OK(status)) return True;
429
430
431         /* try with a notify style */
432         param_len = 6;
433         SSVAL(param, 0, dnum);
434         SSVAL(param, 2, dnum);
435         SSVAL(param, 4, level);
436         status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len, 
437                                 &rparam_len, &rdata_len);
438         if (NT_STATUS_IS_OK(status)) return True;
439
440         /* try with a file name */
441         param_len = 6;
442         SSVAL(param, 0, level);
443         SSVAL(param, 2, 0);
444         SSVAL(param, 4, 0);
445         param_len += push_string(&param[6], fname, -1, STR_TERMINATE | STR_UNICODE);
446
447         status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len, 
448                                 &rparam_len, &rdata_len);
449         if (NT_STATUS_IS_OK(status)) return True;
450
451         /* try with a new file name */
452         param_len = 6;
453         SSVAL(param, 0, level);
454         SSVAL(param, 2, 0);
455         SSVAL(param, 4, 0);
456         param_len += push_string(&param[6], "\\newfile.dat", -1, STR_TERMINATE | STR_UNICODE);
457
458         status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
459                                 &rparam_len, &rdata_len);
460         smbcli_unlink(cli->tree, "\\newfile.dat");
461         smbcli_rmdir(cli->tree, "\\newfile.dat");
462         if (NT_STATUS_IS_OK(status)) return True;
463
464         /* try dfs style  */
465         smbcli_mkdir(cli->tree, "\\testdir");
466         param_len = 2;
467         SSVAL(param, 0, level);
468         param_len += push_string(&param[2], "\\testdir", -1, STR_TERMINATE | STR_UNICODE);
469
470         status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
471                                 &rparam_len, &rdata_len);
472         smbcli_rmdir(cli->tree, "\\testdir");
473         if (NT_STATUS_IS_OK(status)) return True;
474
475         return False;
476 }
477
478
479 BOOL torture_nttrans_scan(void)
480 {
481         static struct smbcli_state *cli;
482         int op, level;
483         const char *fname = "\\scanner.dat";
484         int fnum, dnum;
485
486         printf("starting nttrans scan test\n");
487
488         if (!torture_open_connection(&cli)) {
489                 return False;
490         }
491
492         fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC, 
493                          DENY_NONE);
494         dnum = smbcli_open(cli->tree, "\\", O_RDONLY, DENY_NONE);
495
496         for (op=OP_MIN; op<=OP_MAX; op++) {
497                 printf("Scanning op=%d\n", op);
498                 for (level = 0; level <= 50; level++) {
499                         scan_nttrans(cli, op, level, fnum, dnum, fname);
500                 }
501
502                 for (level = 0x100; level <= 0x130; level++) {
503                         scan_nttrans(cli, op, level, fnum, dnum, fname);
504                 }
505
506                 for (level = 1000; level < 1050; level++) {
507                         scan_nttrans(cli, op, level, fnum, dnum, fname);
508                 }
509         }
510
511         torture_close_connection(cli);
512
513         printf("nttrans scan finished\n");
514         return True;
515 }
516
517
518 /* scan for valid base SMB requests */
519 BOOL torture_smb_scan(void)
520 {
521         static struct smbcli_state *cli;
522         int op;
523         struct smbcli_request *req;
524         NTSTATUS status;
525
526         for (op=0x0;op<=0xFF;op++) {
527                 if (op == SMBreadbraw) continue;
528
529                 if (!torture_open_connection(&cli)) {
530                         return False;
531                 }
532
533                 req = smbcli_request_setup(cli->tree, op, 0, 0);
534
535                 if (!smbcli_request_send(req)) {
536                         smbcli_request_destroy(req);
537                         break;
538                 }
539
540                 usleep(10000);
541                 smbcli_transport_process(cli->transport);
542                 if (req->state > SMBCLI_REQUEST_RECV) {
543                         status = smbcli_request_simple_recv(req);
544                         printf("op=0x%x status=%s\n", op, nt_errstr(status));
545                         torture_close_connection(cli);
546                         continue;
547                 }
548
549                 sleep(1);
550                 smbcli_transport_process(cli->transport);
551                 if (req->state > SMBCLI_REQUEST_RECV) {
552                         status = smbcli_request_simple_recv(req);
553                         printf("op=0x%x status=%s\n", op, nt_errstr(status));
554                 } else {
555                         printf("op=0x%x no reply\n", op);
556                         smbcli_request_destroy(req);
557                         continue; /* don't attempt close! */
558                 }
559
560                 torture_close_connection(cli);
561         }
562
563
564         printf("smb scan finished\n");
565         return True;
566 }