8fdb2999ea1337735fbb39fc5e054dcb678f5ce5
[tprouty/samba.git] / source4 / torture / basic / aliases.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB trans2 alias scanner
4    Copyright (C) Andrew Tridgell 2003
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 "dlinklist.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "torture/torture.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27
28 int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname);
29
30 struct trans2_blobs {
31         struct trans2_blobs *next, *prev;
32         uint16_t level;
33         DATA_BLOB params, data;
34 };
35
36 /* look for aliases for a query */
37 static void gen_aliases(struct smbcli_state *cli, struct smb_trans2 *t2, int level_offset)
38 {
39         TALLOC_CTX *mem_ctx;
40         uint16_t level;
41         struct trans2_blobs *alias_blobs = NULL;
42         struct trans2_blobs *t2b, *t2b2;
43         int count=0, alias_count=0;
44
45         mem_ctx = talloc_init("aliases");
46
47         for (level=0;level<2000;level++) {
48                 NTSTATUS status;
49
50                 SSVAL(t2->in.params.data, level_offset, level);
51                 
52                 status = smb_raw_trans2(cli->tree, mem_ctx, t2);
53                 if (!NT_STATUS_IS_OK(status)) continue;
54
55                 t2b = talloc(mem_ctx, struct trans2_blobs);
56                 t2b->level = level;
57                 t2b->params = t2->out.params;
58                 t2b->data = t2->out.data;
59                 DLIST_ADD(alias_blobs, t2b);
60                 d_printf("\tFound level %4u (0x%03x) of size %3d (0x%02x)\n", 
61                          level, level,
62                          (int)t2b->data.length, (int)t2b->data.length);
63                 count++;
64         }
65
66         d_printf("Found %d levels with success status\n", count);
67
68         for (t2b=alias_blobs; t2b; t2b=t2b->next) {
69                 for (t2b2=alias_blobs; t2b2; t2b2=t2b2->next) {
70                         if (t2b->level >= t2b2->level) continue;
71                         if (data_blob_equal(&t2b->params, &t2b2->params) &&
72                             data_blob_equal(&t2b->data, &t2b2->data)) {
73                                 printf("\tLevel %u (0x%x) and level %u (0x%x) are possible aliases\n", 
74                                        t2b->level, t2b->level, t2b2->level, t2b2->level);
75                                 alias_count++;
76                         }
77                 }
78         }
79
80         d_printf("Found %d aliased levels\n", alias_count);
81         
82         talloc_free(mem_ctx);
83 }
84
85 /* look for qfsinfo aliases */
86 static void qfsinfo_aliases(struct smbcli_state *cli)
87 {
88         struct smb_trans2 t2;
89         uint16_t setup = TRANSACT2_QFSINFO;
90
91         d_printf("\nChecking for QFSINFO aliases\n");
92
93         t2.in.max_param = 0;
94         t2.in.max_data = smb_raw_max_trans_data(cli->tree, 0);
95         t2.in.max_setup = 0;
96         t2.in.flags = 0;
97         t2.in.timeout = 0;
98         t2.in.setup_count = 1;
99         t2.in.setup = &setup;
100         t2.in.params = data_blob(NULL, 2);
101         t2.in.data = data_blob(NULL, 0);
102
103         gen_aliases(cli, &t2, 0);
104 }
105
106 /* look for qfileinfo aliases */
107 static void qfileinfo_aliases(struct smbcli_state *cli)
108 {
109         struct smb_trans2 t2;
110         uint16_t setup = TRANSACT2_QFILEINFO;
111         const char *fname = "\\qfileinfo_aliases.txt";
112         int fnum;
113
114         d_printf("\nChecking for QFILEINFO aliases\n");
115
116         t2.in.max_param = 2;
117         t2.in.max_data = smb_raw_max_trans_data(cli->tree, 2);
118         t2.in.max_setup = 0;
119         t2.in.flags = 0;
120         t2.in.timeout = 0;
121         t2.in.setup_count = 1;
122         t2.in.setup = &setup;
123         t2.in.params = data_blob(NULL, 4);
124         t2.in.data = data_blob(NULL, 0);
125
126         smbcli_unlink(cli->tree, fname);
127         fnum = create_complex_file(cli, cli, fname);
128         if (fnum == -1) {
129                 printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
130         }
131
132         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
133
134         SSVAL(t2.in.params.data, 0, fnum);
135
136         gen_aliases(cli, &t2, 2);
137
138         smbcli_close(cli->tree, fnum);
139         smbcli_unlink(cli->tree, fname);
140 }
141
142
143 /* look for qpathinfo aliases */
144 static void qpathinfo_aliases(struct smbcli_state *cli)
145 {
146         struct smb_trans2 t2;
147         uint16_t setup = TRANSACT2_QPATHINFO;
148         const char *fname = "\\qpathinfo_aliases.txt";
149         int fnum;
150         TALLOC_CTX *mem_ctx;
151
152         mem_ctx = talloc_init("qpathinfo");
153
154         d_printf("\nChecking for QPATHINFO aliases\n");
155
156         t2.in.max_param = 2;
157         t2.in.max_data = smb_raw_max_trans_data(cli->tree, 2);
158         t2.in.max_setup = 0;
159         t2.in.flags = 0;
160         t2.in.timeout = 0;
161         t2.in.setup_count = 1;
162         t2.in.setup = &setup;
163         t2.in.params = data_blob_talloc(mem_ctx, NULL, 6);
164         t2.in.data = data_blob(NULL, 0);
165
166         smbcli_unlink(cli->tree, fname);
167         fnum = create_complex_file(cli, cli, fname);
168         if (fnum == -1) {
169                 printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
170         }
171
172         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
173         smbcli_close(cli->tree, fnum);
174
175         SIVAL(t2.in.params.data, 2, 0);
176
177         smbcli_blob_append_string(cli->session, mem_ctx, &t2.in.params, 
178                                fname, STR_TERMINATE);
179
180         gen_aliases(cli, &t2, 0);
181
182         smbcli_unlink(cli->tree, fname);
183         talloc_free(mem_ctx);
184 }
185
186
187 /* look for trans2 findfirst aliases */
188 static void findfirst_aliases(struct smbcli_state *cli)
189 {
190         struct smb_trans2 t2;
191         uint16_t setup = TRANSACT2_FINDFIRST;
192         const char *fname = "\\findfirst_aliases.txt";
193         int fnum;
194         TALLOC_CTX *mem_ctx;
195
196         mem_ctx = talloc_init("findfirst");
197
198         d_printf("\nChecking for FINDFIRST aliases\n");
199
200         t2.in.max_param = 16;
201         t2.in.max_data = smb_raw_max_trans_data(cli->tree, 16);
202         t2.in.max_setup = 0;
203         t2.in.flags = 0;
204         t2.in.timeout = 0;
205         t2.in.setup_count = 1;
206         t2.in.setup = &setup;
207         t2.in.params = data_blob_talloc(mem_ctx, NULL, 12);
208         t2.in.data = data_blob(NULL, 0);
209
210         smbcli_unlink(cli->tree, fname);
211         fnum = create_complex_file(cli, cli, fname);
212         if (fnum == -1) {
213                 printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
214         }
215
216         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
217         smbcli_close(cli->tree, fnum);
218
219         SSVAL(t2.in.params.data, 0, 0);
220         SSVAL(t2.in.params.data, 2, 1);
221         SSVAL(t2.in.params.data, 4, FLAG_TRANS2_FIND_CLOSE);
222         SSVAL(t2.in.params.data, 6, 0);
223         SIVAL(t2.in.params.data, 8, 0);
224
225         smbcli_blob_append_string(cli->session, mem_ctx, &t2.in.params, 
226                                fname, STR_TERMINATE);
227
228         gen_aliases(cli, &t2, 6);
229
230         smbcli_unlink(cli->tree, fname);
231         talloc_free(mem_ctx);
232 }
233
234
235
236 /* look for aliases for a set function */
237 static void gen_set_aliases(struct smbcli_state *cli, struct smb_trans2 *t2, int level_offset)
238 {
239         TALLOC_CTX *mem_ctx;
240         uint16_t level;
241         struct trans2_blobs *alias_blobs = NULL;
242         struct trans2_blobs *t2b;
243         int count=0, dsize;
244
245         mem_ctx = talloc_init("aliases");
246
247         for (level=1;level<1100;level++) {
248                 NTSTATUS status, status1;
249                 SSVAL(t2->in.params.data, level_offset, level);
250
251                 status1 = NT_STATUS_OK;
252
253                 for (dsize=2; dsize<1024; dsize += 2) {
254                         data_blob_free(&t2->in.data);
255                         t2->in.data = data_blob(NULL, dsize);
256                         data_blob_clear(&t2->in.data);
257                         status = smb_raw_trans2(cli->tree, mem_ctx, t2);
258                         /* some error codes mean that this whole level doesn't exist */
259                         if (NT_STATUS_EQUAL(NT_STATUS_INVALID_LEVEL, status) ||
260                             NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status) ||
261                             NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
262                                 break;
263                         }
264                         if (NT_STATUS_IS_OK(status)) break;
265
266                         /* invalid parameter means that the level exists at this 
267                            size, but the contents are wrong (not surprising with
268                            all zeros!) */
269                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) break;
270
271                         /* this is the usual code for 'wrong size' */
272                         if (NT_STATUS_EQUAL(status, NT_STATUS_INFO_LENGTH_MISMATCH)) {
273                                 continue;
274                         }
275
276                         if (!NT_STATUS_EQUAL(status, status1)) {
277                                 printf("level=%d size=%d %s\n", level, dsize, nt_errstr(status));
278                         }
279                         status1 = status;
280                 }
281
282                 if (!NT_STATUS_IS_OK(status) &&
283                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) continue;
284
285                 t2b = talloc(mem_ctx, struct trans2_blobs);
286                 t2b->level = level;
287                 t2b->params = t2->out.params;
288                 t2b->data = t2->out.data;
289                 DLIST_ADD(alias_blobs, t2b);
290                 d_printf("\tFound level %4u (0x%03x) of size %3d (0x%02x)\n", 
291                          level, level,
292                          (int)t2->in.data.length, (int)t2->in.data.length);
293                 count++;
294         }
295
296         d_printf("Found %d valid levels\n", count);
297         talloc_free(mem_ctx);
298 }
299
300
301
302 /* look for setfileinfo aliases */
303 static void setfileinfo_aliases(struct smbcli_state *cli)
304 {
305         struct smb_trans2 t2;
306         uint16_t setup = TRANSACT2_SETFILEINFO;
307         const char *fname = "\\setfileinfo_aliases.txt";
308         int fnum;
309
310         d_printf("\nChecking for SETFILEINFO aliases\n");
311
312         t2.in.max_param = 2;
313         t2.in.max_data = 0;
314         t2.in.max_setup = 0;
315         t2.in.flags = 0;
316         t2.in.timeout = 0;
317         t2.in.setup_count = 1;
318         t2.in.setup = &setup;
319         t2.in.params = data_blob(NULL, 6);
320         t2.in.data = data_blob(NULL, 0);
321
322         smbcli_unlink(cli->tree, fname);
323         fnum = create_complex_file(cli, cli, fname);
324         if (fnum == -1) {
325                 printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
326         }
327
328         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
329
330         SSVAL(t2.in.params.data, 0, fnum);
331         SSVAL(t2.in.params.data, 4, 0);
332
333         gen_set_aliases(cli, &t2, 2);
334
335         smbcli_close(cli->tree, fnum);
336         smbcli_unlink(cli->tree, fname);
337 }
338
339 /* look for setpathinfo aliases */
340 static void setpathinfo_aliases(struct smbcli_state *cli)
341 {
342         struct smb_trans2 t2;
343         uint16_t setup = TRANSACT2_SETPATHINFO;
344         const char *fname = "\\setpathinfo_aliases.txt";
345         int fnum;
346         TALLOC_CTX *mem_ctx;
347
348         mem_ctx = talloc_init("findfirst");
349
350         d_printf("\nChecking for SETPATHINFO aliases\n");
351
352         t2.in.max_param = 32;
353         t2.in.max_data = smb_raw_max_trans_data(cli->tree, 32);
354         t2.in.max_setup = 0;
355         t2.in.flags = 0;
356         t2.in.timeout = 0;
357         t2.in.setup_count = 1;
358         t2.in.setup = &setup;
359         t2.in.params = data_blob_talloc(mem_ctx, NULL, 4);
360         t2.in.data = data_blob(NULL, 0);
361
362         smbcli_unlink(cli->tree, fname);
363
364         fnum = create_complex_file(cli, cli, fname);
365         if (fnum == -1) {
366                 printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
367         }
368
369         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
370         smbcli_close(cli->tree, fnum);
371
372         SSVAL(t2.in.params.data, 2, 0);
373
374         smbcli_blob_append_string(cli->session, mem_ctx, &t2.in.params, 
375                                fname, STR_TERMINATE);
376
377         gen_set_aliases(cli, &t2, 0);
378
379         if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
380                 printf("unlink: %s\n", smbcli_errstr(cli->tree));
381         }
382         talloc_free(mem_ctx);
383 }
384
385
386 /* look for aliased info levels in trans2 calls */
387 BOOL torture_trans2_aliases(struct torture_context *torture)
388 {
389         struct smbcli_state *cli;
390
391         if (!torture_open_connection(&cli, 0)) {
392                 return False;
393         }
394
395
396         qfsinfo_aliases(cli);
397         qfileinfo_aliases(cli);
398         qpathinfo_aliases(cli);
399         findfirst_aliases(cli);
400         setfileinfo_aliases(cli);
401         setpathinfo_aliases(cli);
402
403         if (!torture_close_connection(cli)) {
404                 return False;
405         }
406
407         return True;
408 }