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