Correctly check for errors in strlower_m() returns.
[kai/samba.git] / source3 / torture / 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 "system/filesys.h"
22 #include "torture/proto.h"
23 #include "libsmb/libsmb.h"
24 #include "../libcli/smb/smbXcli_base.h"
25
26 #define VERBOSE 0
27 #define OP_MIN 0
28 #define OP_MAX 20
29
30 #define DATA_SIZE 1024
31 #define PARAM_SIZE 1024
32
33 /****************************************************************************
34 look for a partial hit
35 ****************************************************************************/
36 static void trans2_check_hit(const char *format, int op, int level, NTSTATUS status)
37 {
38         if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
39             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
40             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
41             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
42             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
43                 return;
44         }
45 #if VERBOSE
46         printf("possible %s hit op=%3d level=%5d status=%s\n",
47                format, op, level, nt_errstr(status));
48 #endif
49 }
50
51 /****************************************************************************
52 check for existance of a trans2 call
53 ****************************************************************************/
54 static NTSTATUS try_trans2(struct cli_state *cli, 
55                          int op,
56                          uint8_t *param, uint8_t *data,
57                          uint32_t param_len, uint32_t data_len,
58                          uint32_t *rparam_len, uint32_t *rdata_len)
59 {
60         uint16_t setup[1];
61         uint8_t *rparam=NULL, *rdata=NULL;
62         NTSTATUS status;
63
64         SSVAL(setup+0, 0, op);
65
66         status = cli_trans(talloc_tos(), cli, SMBtrans2,
67                            NULL, -1, /* name, fid */
68                            op, 0,
69                            NULL, 0, 0, /* setup */
70                            param, param_len, 2,
71                            data, data_len, CLI_BUFFER_SIZE,
72                            NULL,                /* recv_flags2 */
73                            NULL, 0, NULL,       /* rsetup */
74                            &rparam, 0, rparam_len,
75                            &rdata, 0, rdata_len);
76
77         TALLOC_FREE(rdata);
78         TALLOC_FREE(rparam);
79
80         return status;
81 }
82
83
84 static NTSTATUS try_trans2_len(struct cli_state *cli, 
85                              const char *format,
86                              int op, int level,
87                              uint8_t *param, uint8_t *data,
88                              uint32_t param_len, uint32_t *data_len,
89                              uint32_t *rparam_len, uint32_t *rdata_len)
90 {
91         NTSTATUS ret=NT_STATUS_OK;
92
93         ret = try_trans2(cli, op, param, data, param_len,
94                          DATA_SIZE, rparam_len, rdata_len);
95 #if VERBOSE 
96         printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
97 #endif
98         if (!NT_STATUS_IS_OK(ret)) return ret;
99
100         *data_len = 0;
101         while (*data_len < DATA_SIZE) {
102                 ret = try_trans2(cli, op, param, data, param_len,
103                                  *data_len, rparam_len, rdata_len);
104                 if (NT_STATUS_IS_OK(ret)) break;
105                 *data_len += 2;
106         }
107         if (NT_STATUS_IS_OK(ret)) {
108                 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
109                        format, level, *data_len, *rparam_len, *rdata_len);
110         } else {
111                 trans2_check_hit(format, op, level, ret);
112         }
113         return ret;
114 }
115
116 /****************************************************************************
117 check for existance of a trans2 call
118 ****************************************************************************/
119 static bool scan_trans2(struct cli_state *cli, int op, int level, 
120                         int fnum, int dnum, const char *fname)
121 {
122         uint32_t data_len = 0;
123         uint32_t param_len = 0;
124         uint32_t rparam_len, rdata_len;
125         uint8_t *param = NULL;
126         uint8_t data[DATA_SIZE];
127         const char *newfname;
128         const char *dname;
129         NTSTATUS status;
130
131         memset(data, 0, sizeof(data));
132         data_len = 4;
133
134         /* try with a info level only */
135         TALLOC_FREE(param);
136         param = talloc_array(talloc_tos(), uint8_t, 2);
137         if (param == NULL) return True;
138
139         SSVAL(param, 0, level);
140
141         param_len = talloc_get_size(param);
142         status = try_trans2_len(cli, "void", op, level, param, data, param_len, &data_len, 
143                             &rparam_len, &rdata_len);
144         if (NT_STATUS_IS_OK(status)) return True;
145
146         /* try with a file descriptor */
147         TALLOC_FREE(param);
148         param = talloc_array(talloc_tos(), uint8_t, 6);
149         if (param == NULL) return True;
150
151         SSVAL(param, 0, fnum);
152         SSVAL(param, 2, level);
153         SSVAL(param, 4, 0);
154
155         param_len = talloc_get_size(param);
156         status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
157                                 &rparam_len, &rdata_len);
158         if (NT_STATUS_IS_OK(status)) return True;
159
160
161         /* try with a notify style */
162         TALLOC_FREE(param);
163         param = talloc_array(talloc_tos(), uint8_t, 6);
164         if (param == NULL) return True;
165
166         SSVAL(param, 0, dnum);
167         SSVAL(param, 2, dnum);
168         SSVAL(param, 4, level);
169
170         param_len = talloc_get_size(param);
171         status = try_trans2_len(cli, "notify", 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 name */
176         TALLOC_FREE(param);
177         param = talloc_array(talloc_tos(), uint8_t, 6);
178         if (param == NULL) return True;
179
180         SSVAL(param, 0, level);
181         SSVAL(param, 2, 0);
182         SSVAL(param, 4, 0);
183         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
184                                       fname, strlen(fname)+1, NULL);
185         if (param == NULL) return True;
186
187         param_len = talloc_get_size(param);
188         status = try_trans2_len(cli, "fname", 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 new file name */
193         newfname = "\\newfile.dat";
194         TALLOC_FREE(param);
195         param = talloc_array(talloc_tos(), uint8_t, 6);
196         if (param == NULL) return True;
197
198         SSVAL(param, 0, level);
199         SSVAL(param, 2, 0);
200         SSVAL(param, 4, 0);
201         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
202                                       newfname, strlen(newfname)+1, NULL);
203         if (param == NULL) return True;
204
205         param_len = talloc_get_size(param);
206         status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
207                                 &rparam_len, &rdata_len);
208         cli_unlink(cli, newfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
209         cli_rmdir(cli, newfname);
210         if (NT_STATUS_IS_OK(status)) return True;
211
212         /* try dfs style  */
213         dname = "\\testdir";
214         cli_mkdir(cli, dname);
215         TALLOC_FREE(param);
216         param = talloc_array(talloc_tos(), uint8_t, 2);
217         if (param == NULL) return True;
218
219         SSVAL(param, 0, level);
220         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
221                                       dname, strlen(dname)+1, NULL);
222         if (param == NULL) return True;
223
224         param_len = talloc_get_size(param);
225         status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
226                                 &rparam_len, &rdata_len);
227         cli_rmdir(cli, dname);
228         if (NT_STATUS_IS_OK(status)) return True;
229
230         return False;
231 }
232
233
234 bool torture_trans2_scan(int dummy)
235 {
236         static struct cli_state *cli;
237         int op, level;
238         const char *fname = "\\scanner.dat";
239         uint16_t fnum, dnum;
240
241         printf("starting trans2 scan test\n");
242
243         if (!torture_open_connection(&cli, 0)) {
244                 return False;
245         }
246
247         if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, 
248                          DENY_NONE, &fnum))) {
249                 printf("open of %s failed\n", fname);
250                 return false;
251         }
252         if (!NT_STATUS_IS_OK(cli_openx(cli, "\\", O_RDONLY, DENY_NONE, &dnum))) {
253                 printf("open of \\ failed\n");
254                 return false;
255         }
256
257         for (op=OP_MIN; op<=OP_MAX; op++) {
258                 printf("Scanning op=%d\n", op);
259                 for (level = 0; level <= 50; level++) {
260                         scan_trans2(cli, op, level, fnum, dnum, fname);
261                 }
262
263                 for (level = 0x100; level <= 0x130; level++) {
264                         scan_trans2(cli, op, level, fnum, dnum, fname);
265                 }
266
267                 for (level = 1000; level < 1050; level++) {
268                         scan_trans2(cli, op, level, fnum, dnum, fname);
269                 }
270         }
271
272         torture_close_connection(cli);
273
274         printf("trans2 scan finished\n");
275         return True;
276 }
277
278
279
280
281 /****************************************************************************
282 look for a partial hit
283 ****************************************************************************/
284 static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
285 {
286         if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
287             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
288             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
289             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
290             NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
291                 return;
292         }
293 #if VERBOSE
294                 printf("possible %s hit op=%3d level=%5d status=%s\n",
295                        format, op, level, nt_errstr(status));
296 #endif
297 }
298
299 /****************************************************************************
300 check for existance of a nttrans call
301 ****************************************************************************/
302 static NTSTATUS try_nttrans(struct cli_state *cli, 
303                             int op,
304                             uint8_t *param, uint8_t *data,
305                             int32_t param_len, uint32_t data_len,
306                             uint32_t *rparam_len,
307                             uint32_t *rdata_len)
308 {
309         uint8_t *rparam=NULL, *rdata=NULL;
310         NTSTATUS status;
311
312         status = cli_trans(talloc_tos(), cli, SMBnttrans,
313                            NULL, -1, /* name, fid */
314                            op, 0,
315                            NULL, 0, 0, /* setup */
316                            param, param_len, 2,
317                            data, data_len, CLI_BUFFER_SIZE,
318                            NULL,                /* recv_flags2 */
319                            NULL, 0, NULL,       /* rsetup */
320                            &rparam, 0, rparam_len,
321                            &rdata, 0, rdata_len);
322         SAFE_FREE(rdata);
323         SAFE_FREE(rparam);
324
325         return status;
326 }
327
328
329 static NTSTATUS try_nttrans_len(struct cli_state *cli, 
330                              const char *format,
331                              int op, int level,
332                              uint8_t *param, uint8_t *data,
333                              int param_len, uint32_t *data_len,
334                              uint32_t *rparam_len, uint32_t *rdata_len)
335 {
336         NTSTATUS ret=NT_STATUS_OK;
337
338         ret = try_nttrans(cli, op, param, data, param_len,
339                          DATA_SIZE, rparam_len, rdata_len);
340 #if VERBOSE 
341         printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
342 #endif
343         if (!NT_STATUS_IS_OK(ret)) return ret;
344
345         *data_len = 0;
346         while (*data_len < DATA_SIZE) {
347                 ret = try_nttrans(cli, op, param, data, param_len,
348                                  *data_len, rparam_len, rdata_len);
349                 if (NT_STATUS_IS_OK(ret)) break;
350                 *data_len += 2;
351         }
352         if (NT_STATUS_IS_OK(ret)) {
353                 printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
354                        format, level, *data_len, *rparam_len, *rdata_len);
355         } else {
356                 nttrans_check_hit(format, op, level, ret);
357         }
358         return ret;
359 }
360
361 /****************************************************************************
362 check for existance of a nttrans call
363 ****************************************************************************/
364 static bool scan_nttrans(struct cli_state *cli, int op, int level, 
365                         int fnum, int dnum, const char *fname)
366 {
367         uint32_t data_len = 0;
368         uint32_t param_len = 0;
369         uint32_t rparam_len, rdata_len;
370         uint8_t *param = NULL;
371         uint8_t data[DATA_SIZE];
372         NTSTATUS status;
373         const char *newfname;
374         const char *dname;
375
376         memset(data, 0, sizeof(data));
377         data_len = 4;
378
379         /* try with a info level only */
380         TALLOC_FREE(param);
381         param = talloc_array(talloc_tos(), uint8_t, 2);
382         if (param == NULL) return True;
383
384         SSVAL(param, 0, level);
385
386         param_len = talloc_get_size(param);
387         status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len, 
388                             &rparam_len, &rdata_len);
389         if (NT_STATUS_IS_OK(status)) return True;
390
391         /* try with a file descriptor */
392         TALLOC_FREE(param);
393         param = talloc_array(talloc_tos(), uint8_t, 6);
394         if (param == NULL) return True;
395
396         SSVAL(param, 0, fnum);
397         SSVAL(param, 2, level);
398         SSVAL(param, 4, 0);
399
400         param_len = talloc_get_size(param);
401         status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
402                                 &rparam_len, &rdata_len);
403         if (NT_STATUS_IS_OK(status)) return True;
404
405
406         /* try with a notify style */
407         TALLOC_FREE(param);
408         param = talloc_array(talloc_tos(), uint8_t, 6);
409         if (param == NULL) return True;
410
411         SSVAL(param, 0, dnum);
412         SSVAL(param, 2, dnum);
413         SSVAL(param, 4, level);
414
415         param_len = talloc_get_size(param);
416         status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len, 
417                                 &rparam_len, &rdata_len);
418         if (NT_STATUS_IS_OK(status)) return True;
419
420         /* try with a file name */
421         TALLOC_FREE(param);
422         param = talloc_array(talloc_tos(), uint8_t, 6);
423         if (param == NULL) return True;
424
425         SSVAL(param, 0, level);
426         SSVAL(param, 2, 0);
427         SSVAL(param, 4, 0);
428         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
429                                       fname, strlen(fname)+1, NULL);
430         if (param == NULL) return True;
431
432         param_len = talloc_get_size(param);
433         status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len, 
434                                 &rparam_len, &rdata_len);
435         if (NT_STATUS_IS_OK(status)) return True;
436
437         /* try with a new file name */
438         newfname = "\\newfile.dat";
439         TALLOC_FREE(param);
440         param = talloc_array(talloc_tos(), uint8_t, 6);
441         if (param == NULL) return True;
442
443         SSVAL(param, 0, level);
444         SSVAL(param, 2, 0);
445         SSVAL(param, 4, 0);
446         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
447                                       newfname, strlen(newfname)+1, NULL);
448         if (param == NULL) return True;
449
450         param_len = talloc_get_size(param);
451         status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
452                                 &rparam_len, &rdata_len);
453         cli_unlink(cli, newfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
454         cli_rmdir(cli, newfname);
455         if (NT_STATUS_IS_OK(status)) return True;
456
457         /* try dfs style  */
458         dname = "\\testdir";
459         cli_mkdir(cli, dname);
460         TALLOC_FREE(param);
461         param = talloc_array(talloc_tos(), uint8_t, 2);
462         if (param == NULL) return True;
463
464         SSVAL(param, 0, level);
465         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
466                                       dname, strlen(dname)+1, NULL);
467         if (param == NULL) return True;
468
469         param_len = talloc_get_size(param);
470         status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
471                                 &rparam_len, &rdata_len);
472         cli_rmdir(cli, dname);
473         if (NT_STATUS_IS_OK(status)) return True;
474
475         return False;
476 }
477
478
479 bool torture_nttrans_scan(int dummy)
480 {
481         static struct cli_state *cli;
482         int op, level;
483         const char *fname = "\\scanner.dat";
484         uint16_t fnum, dnum;
485
486         printf("starting nttrans scan test\n");
487
488         if (!torture_open_connection(&cli, 0)) {
489                 return False;
490         }
491
492         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, 
493                          DENY_NONE, &fnum);
494         cli_openx(cli, "\\", O_RDONLY, DENY_NONE, &dnum);
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 }