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