smbtorture: check required access for SMB2-GETINFO
[gd/samba-autobuild/.git] / source4 / torture / smb2 / getinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    SMB2 getinfo test suite
5
6    Copyright (C) Andrew Tridgell 2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "libcli/smb/smbXcli_base.h"
26
27 #include "torture/torture.h"
28 #include "torture/smb2/proto.h"
29 #include "torture/util.h"
30
31 static struct {
32         const char *name;
33         uint16_t level;
34         NTSTATUS fstatus;
35         NTSTATUS dstatus;
36         union smb_fileinfo finfo;
37         union smb_fileinfo dinfo;
38 } file_levels[] = {
39 #define LEVEL(x) .name = #x, .level = x
40  { LEVEL(RAW_FILEINFO_BASIC_INFORMATION) },
41  { LEVEL(RAW_FILEINFO_STANDARD_INFORMATION) },
42  { LEVEL(RAW_FILEINFO_INTERNAL_INFORMATION) },
43  { LEVEL(RAW_FILEINFO_EA_INFORMATION) },
44  { LEVEL(RAW_FILEINFO_ACCESS_INFORMATION) },
45  { LEVEL(RAW_FILEINFO_POSITION_INFORMATION) },
46  { LEVEL(RAW_FILEINFO_MODE_INFORMATION) },
47  { LEVEL(RAW_FILEINFO_ALIGNMENT_INFORMATION) },
48  { LEVEL(RAW_FILEINFO_ALL_INFORMATION) },
49  { LEVEL(RAW_FILEINFO_ALT_NAME_INFORMATION) },
50  { LEVEL(RAW_FILEINFO_STREAM_INFORMATION) },
51  { LEVEL(RAW_FILEINFO_COMPRESSION_INFORMATION) },
52  { LEVEL(RAW_FILEINFO_NETWORK_OPEN_INFORMATION) },
53  { LEVEL(RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION) },
54
55  { LEVEL(RAW_FILEINFO_SMB2_ALL_EAS) },
56
57  { LEVEL(RAW_FILEINFO_SMB2_ALL_INFORMATION) },
58  { LEVEL(RAW_FILEINFO_SEC_DESC) }
59 };
60
61 static struct {
62         const char *name;
63         uint16_t level;
64         NTSTATUS status;
65         union smb_fsinfo info;
66 } fs_levels[] = {
67  { LEVEL(RAW_QFS_VOLUME_INFORMATION) },
68  { LEVEL(RAW_QFS_SIZE_INFORMATION) },
69  { LEVEL(RAW_QFS_DEVICE_INFORMATION) },
70  { LEVEL(RAW_QFS_ATTRIBUTE_INFORMATION) },
71  { LEVEL(RAW_QFS_QUOTA_INFORMATION) },
72  { LEVEL(RAW_QFS_FULL_SIZE_INFORMATION) },
73  { LEVEL(RAW_QFS_OBJECTID_INFORMATION) },
74  { LEVEL(RAW_QFS_SECTOR_SIZE_INFORMATION) },
75 };
76
77 #define FNAME "testsmb2_file.dat"
78 #define DNAME "testsmb2_dir"
79
80 /*
81   test fileinfo levels
82 */
83 static bool torture_smb2_fileinfo(struct torture_context *tctx, struct smb2_tree *tree)
84 {
85         struct smb2_handle hfile, hdir;
86         NTSTATUS status;
87         int i;
88
89         status = torture_smb2_testfile(tree, FNAME, &hfile);
90         torture_assert_ntstatus_ok(tctx, status, "Unable to create test file "
91                                    FNAME "\n");
92
93         status = torture_smb2_testdir(tree, DNAME, &hdir);
94         torture_assert_ntstatus_ok(tctx, status, "Unable to create test dir "
95                                    DNAME "\n");
96
97         torture_comment(tctx, "Testing file info levels\n");
98         torture_smb2_all_info(tctx, tree, hfile);
99         torture_smb2_all_info(tctx, tree, hdir);
100
101         for (i=0;i<ARRAY_SIZE(file_levels);i++) {
102                 if (file_levels[i].level == RAW_FILEINFO_SEC_DESC) {
103                         file_levels[i].finfo.query_secdesc.in.secinfo_flags = 0x7;
104                         file_levels[i].dinfo.query_secdesc.in.secinfo_flags = 0x7;
105                 }
106                 if (file_levels[i].level == RAW_FILEINFO_SMB2_ALL_EAS) {
107                         file_levels[i].finfo.all_eas.in.continue_flags =
108                                 SMB2_CONTINUE_FLAG_RESTART;
109                         file_levels[i].dinfo.all_eas.in.continue_flags =
110                                 SMB2_CONTINUE_FLAG_RESTART;
111                 }
112                 file_levels[i].finfo.generic.level = file_levels[i].level;
113                 file_levels[i].finfo.generic.in.file.handle = hfile;
114                 file_levels[i].fstatus = smb2_getinfo_file(tree, tree, &file_levels[i].finfo);
115                 torture_assert_ntstatus_ok(tctx, file_levels[i].fstatus,
116                                            talloc_asprintf(tctx, "%s on file",
117                                                            file_levels[i].name));
118                 file_levels[i].dinfo.generic.level = file_levels[i].level;
119                 file_levels[i].dinfo.generic.in.file.handle = hdir;
120                 file_levels[i].dstatus = smb2_getinfo_file(tree, tree, &file_levels[i].dinfo);
121                 torture_assert_ntstatus_ok(tctx, file_levels[i].dstatus,
122                                            talloc_asprintf(tctx, "%s on dir",
123                                                            file_levels[i].name));
124         }
125
126         return true;
127 }
128
129 /*
130   test granted access when desired access includes
131   FILE_EXECUTE and does not include FILE_READ_DATA
132 */
133 static bool torture_smb2_fileinfo_grant_read(struct torture_context *tctx)
134 {
135         struct smb2_tree *tree;
136         bool ret;
137         struct smb2_handle hfile, hdir;
138         NTSTATUS status;
139         uint32_t file_granted_access, dir_granted_access;
140
141         ret = torture_smb2_connection(tctx, &tree);
142         torture_assert(tctx, ret, "connection failed");
143
144         status = torture_smb2_testfile_access(
145             tree, FNAME, &hfile, SEC_FILE_EXECUTE | SEC_FILE_READ_ATTRIBUTE);
146         torture_assert_ntstatus_ok(tctx, status,
147                                    "Unable to create test file " FNAME "\n");
148         status =
149             torture_smb2_get_allinfo_access(tree, hfile, &file_granted_access);
150         torture_assert_ntstatus_ok(tctx, status,
151                                    "Unable to query test file access ");
152         torture_assert_int_equal(tctx, file_granted_access,
153                                  SEC_FILE_EXECUTE | SEC_FILE_READ_ATTRIBUTE,
154                                  "granted file access ");
155         smb2_util_close(tree, hfile);
156
157         status = torture_smb2_testdir_access(
158             tree, DNAME, &hdir, SEC_FILE_EXECUTE | SEC_FILE_READ_ATTRIBUTE);
159         torture_assert_ntstatus_ok(tctx, status,
160                                    "Unable to create test dir " DNAME "\n");
161         status =
162             torture_smb2_get_allinfo_access(tree, hdir, &dir_granted_access);
163         torture_assert_ntstatus_ok(tctx, status,
164                                    "Unable to query test dir access ");
165         torture_assert_int_equal(tctx, dir_granted_access,
166                                  SEC_FILE_EXECUTE | SEC_FILE_READ_ATTRIBUTE,
167                                  "granted dir access ");
168         smb2_util_close(tree, hdir);
169
170         return true;
171 }
172
173 static bool torture_smb2_fileinfo_normalized(struct torture_context *tctx)
174 {
175         struct smb2_tree *tree = NULL;
176         bool ret;
177         struct smb2_handle hroot;
178         const char *d1 = NULL, *d1l = NULL, *d1u = NULL;
179         struct smb2_handle hd1, hd1l, hd1u;
180         const char *d2 = NULL, *d2l = NULL, *d2u = NULL;
181         struct smb2_handle hd2, hd2l, hd2u;
182         const char *d3 = NULL, *d3l = NULL, *d3u = NULL;
183         struct smb2_handle hd3, hd3l, hd3u;
184         const char *d3s = NULL, *d3sl = NULL, *d3su = NULL, *d3sd = NULL;
185         struct smb2_handle hd3s, hd3sl, hd3su, hd3sd;
186         const char *f4 = NULL, *f4l = NULL, *f4u = NULL, *f4d = NULL;
187         struct smb2_handle hf4, hf4l, hf4u, hf4d;
188         const char *f4s = NULL, *f4sl = NULL, *f4su = NULL, *f4sd = NULL;
189         struct smb2_handle hf4s, hf4sl, hf4su, hf4sd;
190         union smb_fileinfo info = {
191                 .normalized_name_info = {
192                         .level = RAW_FILEINFO_NORMALIZED_NAME_INFORMATION,
193                 },
194         };
195         NTSTATUS status;
196         enum protocol_types protocol;
197         struct smb2_tree *tree_3_0 = NULL;
198         struct smbcli_options options3_0;
199         struct smb2_handle hroot_3_0;
200
201         ret = torture_smb2_connection(tctx, &tree);
202         torture_assert(tctx, ret, "connection failed");
203
204         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
205
206         d1 = talloc_asprintf(tctx, "torture_dIr1N");
207         torture_assert_not_null(tctx, d1, "d1");
208         d1l = strlower_talloc(tctx, d1);
209         torture_assert_not_null(tctx, d1l, "d1l");
210         d1u = strupper_talloc(tctx, d1);
211         torture_assert_not_null(tctx, d1u, "d1u");
212
213         d2 = talloc_asprintf(tctx, "%s\\dIr2Na", d1);
214         torture_assert_not_null(tctx, d2, "d2");
215         d2l = strlower_talloc(tctx, d2);
216         torture_assert_not_null(tctx, d2l, "d2l");
217         d2u = strupper_talloc(tctx, d2);
218         torture_assert_not_null(tctx, d2u, "d2u");
219
220         d3 = talloc_asprintf(tctx, "%s\\dIr3NaM", d2);
221         torture_assert_not_null(tctx, d3, "d3");
222         d3l = strlower_talloc(tctx, d3);
223         torture_assert_not_null(tctx, d3l, "d3l");
224         d3u = strupper_talloc(tctx, d3);
225         torture_assert_not_null(tctx, d3u, "d3u");
226
227         d3s = talloc_asprintf(tctx, "%s:sTrEaM3", d3);
228         torture_assert_not_null(tctx, d3s, "d3s");
229         d3sl = strlower_talloc(tctx, d3s);
230         torture_assert_not_null(tctx, d3sl, "d3sl");
231         d3su = strupper_talloc(tctx, d3s);
232         torture_assert_not_null(tctx, d3su, "d3su");
233         d3sd = talloc_asprintf(tctx, "%s:$DaTa", d3s);
234         torture_assert_not_null(tctx, d3sd, "d3sd");
235
236         f4 = talloc_asprintf(tctx, "%s\\fIlE4NaMe", d3);
237         torture_assert_not_null(tctx, f4, "f4");
238         f4l = strlower_talloc(tctx, f4);
239         torture_assert_not_null(tctx, f4l, "f4l");
240         f4u = strupper_talloc(tctx, f4);
241         torture_assert_not_null(tctx, f4u, "f4u");
242         f4d = talloc_asprintf(tctx, "%s::$dAtA", f4);
243         torture_assert_not_null(tctx, f4d, "f4d");
244
245         f4s = talloc_asprintf(tctx, "%s:StReAm4", f4);
246         torture_assert_not_null(tctx, f4s, "f4s");
247         f4sl = strlower_talloc(tctx, f4s);
248         torture_assert_not_null(tctx, f4sl, "f4sl");
249         f4su = strupper_talloc(tctx, f4s);
250         torture_assert_not_null(tctx, f4su, "f4su");
251         f4sd = talloc_asprintf(tctx, "%s:$dAtA", f4s);
252         torture_assert_not_null(tctx, f4sd, "f4sd");
253
254         status = smb2_util_roothandle(tree, &hroot);
255         torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
256
257         info.normalized_name_info.in.file.handle = hroot;
258         ZERO_STRUCT(info.normalized_name_info.out);
259         status = smb2_getinfo_file(tree, tree, &info);
260         if (protocol < PROTOCOL_SMB3_11) {
261                 /*
262                  * Only SMB 3.1.1 and above should offer this.
263                  */
264                 torture_assert_ntstatus_equal(tctx, status,
265                                               NT_STATUS_NOT_SUPPORTED,
266                                               "getinfo hroot");
267                 torture_skip(tctx, "SMB 3.1.1 not supported");
268         }
269         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
270                 /*
271                  * Not all servers support this.
272                  * (only Windows 10 1803 and higher)
273                  */
274                 torture_skip(tctx, "NORMALIZED_NAME_INFORMATION not supported");
275         }
276         torture_assert_ntstatus_ok(tctx, status, "getinfo hroot");
277         torture_assert(tctx, info.normalized_name_info.out.fname.s == NULL,
278                        "getinfo hroot should be empty");
279
280         smb2_deltree(tree, d1);
281
282         status = torture_smb2_testdir(tree, d1, &hd1);
283         torture_assert_ntstatus_ok(tctx, status, "Unable to create hd1");
284         status = torture_smb2_open(tree, d1l, SEC_RIGHTS_FILE_ALL, &hd1l);
285         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd1l");
286         status = torture_smb2_open(tree, d1u, SEC_RIGHTS_FILE_ALL, &hd1u);
287         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd1u");
288
289         status = torture_smb2_testdir(tree, d2, &hd2);
290         torture_assert_ntstatus_ok(tctx, status, "Unable to create hd2");
291         status = torture_smb2_open(tree, d2l, SEC_RIGHTS_FILE_ALL, &hd2l);
292         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd2l");
293         status = torture_smb2_open(tree, d2u, SEC_RIGHTS_FILE_ALL, &hd2u);
294         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd2u");
295
296         status = torture_smb2_testdir(tree, d3, &hd3);
297         torture_assert_ntstatus_ok(tctx, status, "Unable to create hd3");
298         status = torture_smb2_open(tree, d3l, SEC_RIGHTS_FILE_ALL, &hd3l);
299         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd3l");
300         status = torture_smb2_open(tree, d3u, SEC_RIGHTS_FILE_ALL, &hd3u);
301         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd3u");
302
303         status = torture_smb2_testfile(tree, d3s, &hd3s);
304         torture_assert_ntstatus_ok(tctx, status, "Unable to create hd3s");
305         status = torture_smb2_open(tree, d3sl, SEC_RIGHTS_FILE_ALL, &hd3sl);
306         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd3sl");
307         status = torture_smb2_open(tree, d3su, SEC_RIGHTS_FILE_ALL, &hd3su);
308         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd3su");
309         status = torture_smb2_open(tree, d3sd, SEC_RIGHTS_FILE_ALL, &hd3sd);
310         torture_assert_ntstatus_ok(tctx, status, "Unable to open hd3sd");
311
312         status = torture_smb2_testfile(tree, f4, &hf4);
313         torture_assert_ntstatus_ok(tctx, status, "Unable to create hf4");
314         status = torture_smb2_open(tree, f4l, SEC_RIGHTS_FILE_ALL, &hf4l);
315         torture_assert_ntstatus_ok(tctx, status, "Unable to open hf4l");
316         status = torture_smb2_open(tree, f4u, SEC_RIGHTS_FILE_ALL, &hf4u);
317         torture_assert_ntstatus_ok(tctx, status, "Unable to open hf4u");
318         status = torture_smb2_open(tree, f4d, SEC_RIGHTS_FILE_ALL, &hf4d);
319         torture_assert_ntstatus_ok(tctx, status, "Unable to open hf4d");
320
321         status = torture_smb2_testfile(tree, f4s, &hf4s);
322         torture_assert_ntstatus_ok(tctx, status, "Unable to create hf4s");
323         status = torture_smb2_open(tree, f4sl, SEC_RIGHTS_FILE_ALL, &hf4sl);
324         torture_assert_ntstatus_ok(tctx, status, "Unable to open hf4sl");
325         status = torture_smb2_open(tree, f4su, SEC_RIGHTS_FILE_ALL, &hf4su);
326         torture_assert_ntstatus_ok(tctx, status, "Unable to open hf4su");
327         status = torture_smb2_open(tree, f4sd, SEC_RIGHTS_FILE_ALL, &hf4sd);
328         torture_assert_ntstatus_ok(tctx, status, "Unable to open hf4sd");
329
330         info.normalized_name_info.in.file.handle = hd1;
331         ZERO_STRUCT(info.normalized_name_info.out);
332         status = smb2_getinfo_file(tree, tree, &info);
333         torture_assert_ntstatus_ok(tctx, status, "getinfo hd1");
334         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
335                                  d1, "getinfo hd1");
336         info.normalized_name_info.in.file.handle = hd1l;
337         ZERO_STRUCT(info.normalized_name_info.out);
338         status = smb2_getinfo_file(tree, tree, &info);
339         torture_assert_ntstatus_ok(tctx, status, "getinfo hd1l");
340         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
341                                  d1, "getinfo hd1l");
342         info.normalized_name_info.in.file.handle = hd1u;
343         ZERO_STRUCT(info.normalized_name_info.out);
344         status = smb2_getinfo_file(tree, tree, &info);
345         torture_assert_ntstatus_ok(tctx, status, "getinfo hd1u");
346         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
347                                  d1, "getinfo hd1u");
348
349         info.normalized_name_info.in.file.handle = hd2;
350         ZERO_STRUCT(info.normalized_name_info.out);
351         status = smb2_getinfo_file(tree, tree, &info);
352         torture_assert_ntstatus_ok(tctx, status, "getinfo hd2");
353         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
354                                  d2, "getinfo hd2");
355         info.normalized_name_info.in.file.handle = hd2l;
356         ZERO_STRUCT(info.normalized_name_info.out);
357         status = smb2_getinfo_file(tree, tree, &info);
358         torture_assert_ntstatus_ok(tctx, status, "getinfo hd2l");
359         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
360                                  d2, "getinfo hd2l");
361         info.normalized_name_info.in.file.handle = hd2u;
362         ZERO_STRUCT(info.normalized_name_info.out);
363         status = smb2_getinfo_file(tree, tree, &info);
364         torture_assert_ntstatus_ok(tctx, status, "getinfo hd2u");
365         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
366                                  d2, "getinfo hd2u");
367
368         info.normalized_name_info.in.file.handle = hd3;
369         ZERO_STRUCT(info.normalized_name_info.out);
370         status = smb2_getinfo_file(tree, tree, &info);
371         torture_assert_ntstatus_ok(tctx, status, "getinfo hd3");
372         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
373                                  d3, "getinfo hd3");
374         info.normalized_name_info.in.file.handle = hd3l;
375         ZERO_STRUCT(info.normalized_name_info.out);
376         status = smb2_getinfo_file(tree, tree, &info);
377         torture_assert_ntstatus_ok(tctx, status, "getinfo hd3l");
378         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
379                                  d3, "getinfo hd3l");
380         info.normalized_name_info.in.file.handle = hd3u;
381         ZERO_STRUCT(info.normalized_name_info.out);
382         status = smb2_getinfo_file(tree, tree, &info);
383         torture_assert_ntstatus_ok(tctx, status, "getinfo hd3u");
384         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
385                                  d3, "getinfo hd3u");
386
387         info.normalized_name_info.in.file.handle = hd3s;
388         ZERO_STRUCT(info.normalized_name_info.out);
389         status = smb2_getinfo_file(tree, tree, &info);
390         torture_assert_ntstatus_ok(tctx, status, "getinfo hd3s");
391         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
392                                  d3s, "getinfo hd3s");
393         info.normalized_name_info.in.file.handle = hd3sl;
394         ZERO_STRUCT(info.normalized_name_info.out);
395         status = smb2_getinfo_file(tree, tree, &info);
396         torture_assert_ntstatus_ok(tctx, status, "getinfo hd3sl");
397         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
398                                  d3s, "getinfo hd3sl");
399         info.normalized_name_info.in.file.handle = hd3su;
400         ZERO_STRUCT(info.normalized_name_info.out);
401         status = smb2_getinfo_file(tree, tree, &info);
402         torture_assert_ntstatus_ok(tctx, status, "getinfo hd3su");
403         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
404                                  d3s, "getinfo hd3su");
405         info.normalized_name_info.in.file.handle = hd3sd;
406         ZERO_STRUCT(info.normalized_name_info.out);
407         status = smb2_getinfo_file(tree, tree, &info);
408         torture_assert_ntstatus_ok(tctx, status, "getinfo hd3sd");
409         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
410                                  d3s, "getinfo hd3sd");
411
412         info.normalized_name_info.in.file.handle = hf4;
413         ZERO_STRUCT(info.normalized_name_info.out);
414         status = smb2_getinfo_file(tree, tree, &info);
415         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4");
416         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
417                                  f4, "getinfo hf4");
418         info.normalized_name_info.in.file.handle = hf4l;
419         ZERO_STRUCT(info.normalized_name_info.out);
420         status = smb2_getinfo_file(tree, tree, &info);
421         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4l");
422         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
423                                  f4, "getinfo hf4l");
424         info.normalized_name_info.in.file.handle = hf4u;
425         ZERO_STRUCT(info.normalized_name_info.out);
426         status = smb2_getinfo_file(tree, tree, &info);
427         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4u");
428         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
429                                  f4, "getinfo hf4u");
430         info.normalized_name_info.in.file.handle = hf4d;
431         ZERO_STRUCT(info.normalized_name_info.out);
432         status = smb2_getinfo_file(tree, tree, &info);
433         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4d");
434         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
435                                  f4, "getinfo hf4d");
436
437         info.normalized_name_info.in.file.handle = hf4s;
438         ZERO_STRUCT(info.normalized_name_info.out);
439         status = smb2_getinfo_file(tree, tree, &info);
440         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4s");
441         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
442                                  f4s, "getinfo hf4s");
443         info.normalized_name_info.in.file.handle = hf4sl;
444         ZERO_STRUCT(info.normalized_name_info.out);
445         status = smb2_getinfo_file(tree, tree, &info);
446         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4sl");
447         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
448                                  f4s, "getinfo hf4sl");
449         info.normalized_name_info.in.file.handle = hf4su;
450         ZERO_STRUCT(info.normalized_name_info.out);
451         status = smb2_getinfo_file(tree, tree, &info);
452         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4su");
453         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
454                                  f4s, "getinfo hf4su");
455         info.normalized_name_info.in.file.handle = hf4sd;
456         ZERO_STRUCT(info.normalized_name_info.out);
457         status = smb2_getinfo_file(tree, tree, &info);
458         torture_assert_ntstatus_ok(tctx, status, "getinfo hf4sd");
459         torture_assert_str_equal(tctx, info.normalized_name_info.out.fname.s,
460                                  f4s, "getinfo hf4sd");
461
462         /* Set max protocol to SMB 3.0.2 */
463         options3_0 = tree->session->transport->options;
464         options3_0.max_protocol = PROTOCOL_SMB3_02;
465         options3_0.client_guid = GUID_zero();
466         ret = torture_smb2_connection_ext(tctx, 0, &options3_0, &tree_3_0);
467         torture_assert(tctx, ret, "connection with SMB < 3.1.1 failed");
468
469         status = smb2_util_roothandle(tree_3_0, &hroot_3_0);
470         torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle 3_0");
471
472         info.normalized_name_info.in.file.handle = hroot_3_0;
473         ZERO_STRUCT(info.normalized_name_info.out);
474         status = smb2_getinfo_file(tree_3_0, tree_3_0, &info);
475         torture_assert_ntstatus_equal(tctx, status,
476                                       NT_STATUS_NOT_SUPPORTED,
477                                       "getinfo hroot");
478
479         return true;
480 }
481
482 /*
483   test fsinfo levels
484 */
485 static bool torture_smb2_fsinfo(struct torture_context *tctx)
486 {
487         bool ret;
488         struct smb2_tree *tree;
489         int i;
490         NTSTATUS status;
491         struct smb2_handle handle;
492
493         torture_comment(tctx, "Testing fsinfo levels\n");
494
495         ret = torture_smb2_connection(tctx, &tree);
496         torture_assert(tctx, ret, "connection failed");
497
498         status = smb2_util_roothandle(tree, &handle);
499         torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
500
501         for (i=0;i<ARRAY_SIZE(fs_levels);i++) {
502                 fs_levels[i].info.generic.level = fs_levels[i].level;
503                 fs_levels[i].info.generic.handle = handle;
504                 fs_levels[i].status = smb2_getinfo_fs(tree, tree, &fs_levels[i].info);
505                 torture_assert_ntstatus_ok(tctx, fs_levels[i].status,
506                                            fs_levels[i].name);
507         }
508
509         return true;
510 }
511
512 static bool torture_smb2_buffercheck_err(struct torture_context *tctx,
513                                          struct smb2_tree *tree,
514                                          struct smb2_getinfo *b,
515                                          size_t fixed,
516                                          DATA_BLOB full)
517 {
518         size_t i;
519
520         for (i=0; i<=full.length; i++) {
521                 NTSTATUS status;
522
523                 b->in.output_buffer_length = i;
524
525                 status = smb2_getinfo(tree, tree, b);
526
527                 if (i < fixed) {
528                         torture_assert_ntstatus_equal(
529                                 tctx, status, NT_STATUS_INFO_LENGTH_MISMATCH,
530                                 "Wrong error code small buffer");
531                         continue;
532                 }
533
534                 if (i<full.length) {
535                         torture_assert_ntstatus_equal(
536                                 tctx, status, STATUS_BUFFER_OVERFLOW,
537                                 "Wrong error code for large buffer");
538                         /*
539                          * TODO: compare the output buffer. That seems a bit
540                          * difficult, because for level 5 for example the
541                          * label length is adjusted to what is there. And some
542                          * reserved fields seem to be not initialized to 0.
543                          */
544                         TALLOC_FREE(b->out.blob.data);
545                         continue;
546                 }
547
548                 torture_assert_ntstatus_equal(
549                         tctx, status, NT_STATUS_OK,
550                         "Wrong error code for right sized buffer");
551         }
552
553         return true;
554 }
555
556 struct level_buffersize {
557         int level;
558         size_t fixed;
559 };
560
561 static bool torture_smb2_qfs_buffercheck(struct torture_context *tctx)
562 {
563         bool ret;
564         struct smb2_tree *tree;
565         NTSTATUS status;
566         struct smb2_handle handle;
567         int i;
568
569         struct level_buffersize levels[] = {
570                 { 1, 24 },      /* We don't have proper defines here */
571                 { 3, 24 },
572                 { 4, 8 },
573                 { 5, 16 },
574                 { 6, 48 },
575                 { 7, 32 },
576                 { 11, 28 },
577         };
578
579         torture_comment(tctx, "Testing SMB2_GETINFO_FS buffer sizes\n");
580
581         ret = torture_smb2_connection(tctx, &tree);
582         torture_assert(tctx, ret, "connection failed");
583
584         status = smb2_util_roothandle(tree, &handle);
585         torture_assert_ntstatus_ok(
586                 tctx, status, "Unable to create root handle");
587
588         for (i=0; i<ARRAY_SIZE(levels); i++) {
589                 struct smb2_getinfo b;
590
591                 if (TARGET_IS_SAMBA3(tctx) &&
592                     ((levels[i].level == 6) || (levels[i].level == 11))) {
593                         continue;
594                 }
595
596                 ZERO_STRUCT(b);
597                 b.in.info_type                  = SMB2_0_INFO_FILESYSTEM;
598                 b.in.info_class                 = levels[i].level;
599                 b.in.file.handle                = handle;
600                 b.in.output_buffer_length       = 65535;
601
602                 status = smb2_getinfo(tree, tree, &b);
603
604                 torture_assert_ntstatus_equal(
605                         tctx, status, NT_STATUS_OK,
606                         "Wrong error code for large buffer");
607
608                 ret = torture_smb2_buffercheck_err(
609                         tctx, tree, &b, levels[i].fixed, b.out.blob);
610                 if (!ret) {
611                         return ret;
612                 }
613         }
614
615         return true;
616 }
617
618 static bool torture_smb2_qfile_buffercheck(struct torture_context *tctx)
619 {
620         bool ret;
621         struct smb2_tree *tree;
622         struct smb2_create c;
623         NTSTATUS status;
624         struct smb2_handle handle;
625         int i;
626
627         struct level_buffersize levels[] = {
628                 { 4, 40 },
629                 { 5, 24 },
630                 { 6, 8 },
631                 { 7, 4 },
632                 { 8, 4 },
633                 { 16, 4 },
634                 { 17, 4 },
635                 { 18, 104 },
636                 { 21, 8 },
637                 { 22, 32 },
638                 { 28, 16 },
639                 { 34, 56 },
640                 { 35, 8 },
641         };
642
643         torture_comment(tctx, "Testing SMB2_GETINFO_FILE buffer sizes\n");
644
645         ret = torture_smb2_connection(tctx, &tree);
646         torture_assert(tctx, ret, "connection failed");
647
648         ZERO_STRUCT(c);
649         c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
650         c.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
651         c.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
652         c.in.share_access =
653                 NTCREATEX_SHARE_ACCESS_DELETE|
654                 NTCREATEX_SHARE_ACCESS_READ|
655                 NTCREATEX_SHARE_ACCESS_WRITE;
656         c.in.create_options = 0;
657         c.in.fname = "bufsize.txt";
658
659         c.in.eas.num_eas = 2;
660         c.in.eas.eas = talloc_array(tree, struct ea_struct, 2);
661         c.in.eas.eas[0].flags = 0;
662         c.in.eas.eas[0].name.s = "EAONE";
663         c.in.eas.eas[0].value = data_blob_talloc(c.in.eas.eas, "VALUE1", 6);
664         c.in.eas.eas[1].flags = 0;
665         c.in.eas.eas[1].name.s = "SECONDEA";
666         c.in.eas.eas[1].value = data_blob_talloc(c.in.eas.eas, "ValueTwo", 8);
667
668         status = smb2_create(tree, tree, &c);
669         torture_assert_ntstatus_ok(
670                 tctx, status, "Unable to create test file");
671
672         handle = c.out.file.handle;
673
674         for (i=0; i<ARRAY_SIZE(levels); i++) {
675                 struct smb2_getinfo b;
676
677                 ZERO_STRUCT(b);
678                 b.in.info_type                  = SMB2_0_INFO_FILE;
679                 b.in.info_class                 = levels[i].level;
680                 b.in.file.handle                = handle;
681                 b.in.output_buffer_length       = 65535;
682
683                 status = smb2_getinfo(tree, tree, &b);
684                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
685                         continue;
686                 }
687                 torture_assert_ntstatus_equal(
688                         tctx, status, NT_STATUS_OK,
689                         "Wrong error code for large buffer");
690
691                 ret = torture_smb2_buffercheck_err(
692                         tctx, tree, &b, levels[i].fixed, b.out.blob);
693                 if (!ret) {
694                         return ret;
695                 }
696         }
697         return true;
698 }
699
700 static bool torture_smb2_qsec_buffercheck(struct torture_context *tctx)
701 {
702         struct smb2_getinfo b;
703         bool ret;
704         struct smb2_tree *tree;
705         struct smb2_create c;
706         NTSTATUS status;
707         struct smb2_handle handle;
708
709         torture_comment(tctx, "Testing SMB2_GETINFO_SECURITY buffer sizes\n");
710
711         ret = torture_smb2_connection(tctx, &tree);
712         torture_assert(tctx, ret, "connection failed");
713
714         ZERO_STRUCT(c);
715         c.in.oplock_level = 0;
716         c.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE |
717                 SEC_DIR_LIST | SEC_STD_READ_CONTROL;
718         c.in.file_attributes   = 0;
719         c.in.create_disposition = NTCREATEX_DISP_OPEN;
720         c.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
721                 NTCREATEX_SHARE_ACCESS_DELETE;
722         c.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
723         c.in.fname = "";
724
725         status = smb2_create(tree, tree, &c);
726         torture_assert_ntstatus_ok(
727                 tctx, status, "Unable to create root handle");
728
729         handle = c.out.file.handle;
730
731         ZERO_STRUCT(b);
732         b.in.info_type                  = SMB2_0_INFO_SECURITY;
733         b.in.info_class                 = 0;
734         b.in.file.handle                = handle;
735         b.in.output_buffer_length       = 0;
736
737         status = smb2_getinfo(tree, tree, &b);
738         torture_assert_ntstatus_equal(
739                 tctx, status, NT_STATUS_BUFFER_TOO_SMALL,
740                 "Wrong error code for large buffer");
741
742         b.in.output_buffer_length       = 1;
743         status = smb2_getinfo(tree, tree, &b);
744         torture_assert_ntstatus_equal(
745                 tctx, status, NT_STATUS_BUFFER_TOO_SMALL,
746                 "Wrong error code for large buffer");
747
748         return true;
749 }
750
751 /* basic testing of all SMB2 getinfo levels
752 */
753 static bool torture_smb2_getinfo(struct torture_context *tctx)
754 {
755         struct smb2_tree *tree;
756         bool ret = true;
757         NTSTATUS status;
758
759         ret = torture_smb2_connection(tctx, &tree);
760         torture_assert(tctx, ret, "connection failed");
761
762         smb2_deltree(tree, FNAME);
763         smb2_deltree(tree, DNAME);
764
765         status = torture_setup_complex_file(tctx, tree, FNAME);
766         torture_assert_ntstatus_ok(tctx, status,
767                                    "setup complex file " FNAME);
768
769         status = torture_setup_complex_file(tctx, tree, FNAME ":streamtwo");
770         torture_assert_ntstatus_ok(tctx, status,
771                                    "setup complex file " FNAME ":streamtwo");
772
773         status = torture_setup_complex_dir(tctx, tree, DNAME);
774         torture_assert_ntstatus_ok(tctx, status,
775                                    "setup complex dir " DNAME);
776
777         status = torture_setup_complex_file(tctx, tree, DNAME ":streamtwo");
778         torture_assert_ntstatus_ok(tctx, status,
779                                    "setup complex dir " DNAME ":streamtwo");
780
781         ret &= torture_smb2_fileinfo(tctx, tree);
782
783         return ret;
784 }
785
786 #undef LEVEL
787 #define LEVEL(l, u, ua, ra) \
788         .name = #l, \
789         .level = l, \
790         .unrestricted = u, \
791         .unrestricted_access = ua, \
792         .required_access = ra
793
794 static struct {
795         const char *name;
796         uint16_t level;
797         bool unrestricted;
798         uint32_t unrestricted_access;
799         uint32_t required_access;
800 } file_levels_access[] = {
801         /*
802          * The following info levels are not checked:
803          * - FileFullEaInformation and FileIdInformation:
804          *   not implemented by the s4/libcli/raw
805          * - all pipe infolevels: that should be tested elsewhere by RPC tests
806          */
807
808         /*
809          * The following allow unrestricted access, so requesting
810          * SEC_FILE_READ_ATTRIBUTE works, SEC_FILE_READ_ATTRIBUTE or
811          * SEC_FILE_READ_EA as well of course.
812          */
813         { LEVEL(RAW_FILEINFO_STANDARD_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
814         { LEVEL(RAW_FILEINFO_INTERNAL_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
815         { LEVEL(RAW_FILEINFO_ACCESS_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
816         { LEVEL(RAW_FILEINFO_POSITION_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
817         { LEVEL(RAW_FILEINFO_MODE_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
818         { LEVEL(RAW_FILEINFO_ALIGNMENT_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
819         { LEVEL(RAW_FILEINFO_ALT_NAME_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
820         { LEVEL(RAW_FILEINFO_STREAM_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
821         { LEVEL(RAW_FILEINFO_COMPRESSION_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
822         { LEVEL(RAW_FILEINFO_NORMALIZED_NAME_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
823         { LEVEL(RAW_FILEINFO_EA_INFORMATION, true, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_EA) },
824
825         /*
826          * The following require either SEC_FILE_READ_ATTRIBUTE or
827          * SEC_FILE_READ_EA.
828          */
829         { LEVEL(RAW_FILEINFO_BASIC_INFORMATION, false, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
830         { LEVEL(RAW_FILEINFO_ALL_INFORMATION, false, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
831         { LEVEL(RAW_FILEINFO_NETWORK_OPEN_INFORMATION, false, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
832         { LEVEL(RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, false, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
833         { LEVEL(RAW_FILEINFO_SMB2_ALL_INFORMATION, false, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_ATTRIBUTE) },
834         { LEVEL(RAW_FILEINFO_SMB2_ALL_EAS, false, SEC_STD_SYNCHRONIZE, SEC_FILE_READ_EA) },
835         /* Also try SEC_FILE_READ_ATTRIBUTE to show that it is the wrong one */
836         { LEVEL(RAW_FILEINFO_SMB2_ALL_EAS, false, SEC_FILE_READ_ATTRIBUTE, SEC_FILE_READ_EA) },
837         { LEVEL(RAW_FILEINFO_SEC_DESC, false, SEC_STD_SYNCHRONIZE, SEC_STD_READ_CONTROL) },
838         /* Also try SEC_FILE_READ_ATTRIBUTE to show that it is the wrong one */
839         { LEVEL(RAW_FILEINFO_SEC_DESC, false, SEC_FILE_READ_ATTRIBUTE, SEC_STD_READ_CONTROL) }
840 };
841
842
843 /*
844   test fileinfo levels
845 */
846 static bool torture_smb2_getfinfo_access(struct torture_context *tctx,
847                                          struct smb2_tree *tree)
848 {
849         const char *fname = "torture_smb2_getfinfo_access";
850         struct smb2_handle hfile;
851         NTSTATUS status;
852         bool ret = true;
853         int i;
854
855         smb2_deltree(tree, fname);
856
857         torture_setup_complex_file(tctx, tree, fname);
858
859         for (i = 0; i < ARRAY_SIZE(file_levels_access); i++) {
860                 union smb_fileinfo finfo;
861                 NTSTATUS expected_status;
862
863                 /*
864                  * First open with unrestricted_access, SEC_STD_SYNCHRONIZE for
865                  * most tests, info levels with unrestricted=true should allow
866                  * this.
867                  */
868                 status = torture_smb2_testfile_access(
869                         tree, fname, &hfile, file_levels_access[i].unrestricted_access);
870                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
871                                            "Unable to open test file\n");
872
873                 if (file_levels_access[i].level == RAW_FILEINFO_SEC_DESC) {
874                         finfo.query_secdesc.in.secinfo_flags = 0x7;
875                 }
876                 if (file_levels_access[i].level == RAW_FILEINFO_SMB2_ALL_EAS) {
877                         finfo.all_eas.in.continue_flags =
878                                 SMB2_CONTINUE_FLAG_RESTART;
879                 }
880
881                 finfo.generic.level = file_levels_access[i].level;
882                 finfo.generic.in.file.handle = hfile;
883
884                 if (file_levels_access[i].unrestricted) {
885                         expected_status = NT_STATUS_OK;
886                 } else {
887                         expected_status = NT_STATUS_ACCESS_DENIED;
888                 }
889
890                 status = smb2_getinfo_file(tree, tree, &finfo);
891                 torture_assert_ntstatus_equal_goto(
892                         tctx, status, expected_status, ret, done,
893                         talloc_asprintf(tctx, "Level %s failed\n",
894                                         file_levels_access[i].name));
895
896                 smb2_util_close(tree, hfile);
897
898                 /*
899                  * Now open with expected access, getinfo should work.
900                  */
901                 status = torture_smb2_testfile_access(
902                         tree, fname, &hfile, file_levels_access[i].required_access);
903                 torture_assert_ntstatus_ok_goto(
904                         tctx, status, ret, done,
905                         "Unable to open test file\n");
906
907                 if (file_levels_access[i].level == RAW_FILEINFO_SEC_DESC) {
908                         finfo.query_secdesc.in.secinfo_flags = 0x7;
909                 }
910                 if (file_levels_access[i].level == RAW_FILEINFO_SMB2_ALL_EAS) {
911                         finfo.all_eas.in.continue_flags =
912                                 SMB2_CONTINUE_FLAG_RESTART;
913                 }
914                 finfo.generic.level = file_levels_access[i].level;
915                 finfo.generic.in.file.handle = hfile;
916
917                 status = smb2_getinfo_file(tree, tree, &finfo);
918                 torture_assert_ntstatus_ok_goto(
919                         tctx, status, ret, done,
920                         talloc_asprintf(tctx, "%s on file",
921                                         file_levels_access[i].name));
922
923                 smb2_util_close(tree, hfile);
924         }
925
926 done:
927         smb2_deltree(tree, fname);
928         return ret;
929 }
930
931 struct torture_suite *torture_smb2_getinfo_init(TALLOC_CTX *ctx)
932 {
933         struct torture_suite *suite = torture_suite_create(
934                 ctx, "getinfo");
935
936         torture_suite_add_simple_test(suite, "complex", torture_smb2_getinfo);
937         torture_suite_add_simple_test(suite, "fsinfo",  torture_smb2_fsinfo);
938         torture_suite_add_simple_test(suite, "qfs_buffercheck",
939                                       torture_smb2_qfs_buffercheck);
940         torture_suite_add_simple_test(suite, "qfile_buffercheck",
941                                       torture_smb2_qfile_buffercheck);
942         torture_suite_add_simple_test(suite, "qsec_buffercheck",
943                                       torture_smb2_qsec_buffercheck);
944         torture_suite_add_simple_test(suite, "granted",
945                                       torture_smb2_fileinfo_grant_read);
946         torture_suite_add_simple_test(suite, "normalized",
947                                       torture_smb2_fileinfo_normalized);
948         torture_suite_add_1smb2_test(suite, "getinfo_access",
949                                      torture_smb2_getfinfo_access);
950         return suite;
951 }