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