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