Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : openattr tester
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) David Mulder 2019
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "libcli/smb2/smb2.h"
25 : #include "libcli/smb2/smb2_calls.h"
26 : #include "torture/torture.h"
27 : #include "libcli/security/security_descriptor.h"
28 : #include "torture/smb2/proto.h"
29 :
30 : static const uint32_t open_attrs_table[] = {
31 : FILE_ATTRIBUTE_NORMAL,
32 : FILE_ATTRIBUTE_ARCHIVE,
33 : FILE_ATTRIBUTE_READONLY,
34 : FILE_ATTRIBUTE_HIDDEN,
35 : FILE_ATTRIBUTE_SYSTEM,
36 :
37 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
38 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
39 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
40 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
41 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
42 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
43 :
44 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
45 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
46 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
47 : FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
48 : };
49 :
50 : struct trunc_open_results {
51 : unsigned int num;
52 : uint32_t init_attr;
53 : uint32_t trunc_attr;
54 : uint32_t result_attr;
55 : };
56 :
57 : static const struct trunc_open_results attr_results[] = {
58 : { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
59 : { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
60 : { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
61 : { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
62 : { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
63 : { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
64 : { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
65 : { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
66 : { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
67 : { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
68 : { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
69 : { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
70 : { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
71 : { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
72 : { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
73 : { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
74 : { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
75 : { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
76 : { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
77 : { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
78 : { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
79 : { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
80 : { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
81 : { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
82 : { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
83 : { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
84 : };
85 :
86 249 : static NTSTATUS smb2_setatr(struct smb2_tree *tree, const char *name,
87 : uint32_t attrib)
88 : {
89 0 : NTSTATUS status;
90 249 : struct smb2_create create_io = {0};
91 0 : union smb_setfileinfo io;
92 :
93 249 : create_io.in.desired_access = SEC_FILE_READ_DATA |
94 : SEC_FILE_WRITE_ATTRIBUTE;
95 249 : create_io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
96 249 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
97 249 : create_io.in.create_disposition = NTCREATEX_DISP_OPEN;
98 249 : create_io.in.fname = name;
99 249 : status = smb2_create(tree, tree, &create_io);
100 249 : if (!NT_STATUS_IS_OK(status)) {
101 5 : return status;
102 : }
103 :
104 244 : ZERO_STRUCT(io);
105 244 : io.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION;
106 244 : io.basic_info.in.file.handle = create_io.out.file.handle;
107 244 : io.basic_info.in.attrib = attrib;
108 244 : status = smb2_setinfo_file(tree, &io);
109 244 : if (!NT_STATUS_IS_OK(status)) {
110 0 : return status;
111 : }
112 :
113 244 : status = smb2_util_close(tree, create_io.out.file.handle);
114 244 : if (!NT_STATUS_IS_OK(status)) {
115 0 : return status;
116 : }
117 :
118 244 : return status;
119 : }
120 :
121 5 : bool torture_smb2_openattrtest(struct torture_context *tctx,
122 : struct smb2_tree *tree)
123 : {
124 0 : NTSTATUS status;
125 5 : const char *fname = "openattr.file";
126 0 : uint16_t attr;
127 0 : unsigned int i, j, k, l;
128 5 : int ret = true;
129 :
130 85 : for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
131 80 : struct smb2_create create_io = {0};
132 80 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
133 80 : smb2_util_unlink(tree, fname);
134 80 : create_io.in.create_flags = 0;
135 80 : create_io.in.desired_access = SEC_FILE_WRITE_DATA;
136 80 : create_io.in.file_attributes = open_attrs_table[i];
137 80 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
138 80 : create_io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
139 80 : create_io.in.create_options = 0;
140 80 : create_io.in.security_flags = 0;
141 80 : create_io.in.fname = fname;
142 80 : status = smb2_create(tree, tctx, &create_io);
143 80 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
144 : talloc_asprintf(tctx, "open %d (1) of %s failed (%s)",
145 : i, fname, nt_errstr(status)));
146 :
147 80 : status = smb2_util_close(tree, create_io.out.file.handle);
148 80 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
149 : talloc_asprintf(tctx, "close %d (1) of %s failed (%s)",
150 : i, fname, nt_errstr(status)));
151 :
152 1360 : for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
153 1280 : create_io = (struct smb2_create){0};
154 1280 : create_io.in.create_flags = 0;
155 1280 : create_io.in.desired_access = SEC_FILE_READ_DATA|
156 : SEC_FILE_WRITE_DATA;
157 1280 : create_io.in.file_attributes = open_attrs_table[j];
158 1280 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
159 1280 : create_io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
160 1280 : create_io.in.create_options = 0;
161 1280 : create_io.in.security_flags = 0;
162 1280 : create_io.in.fname = fname;
163 1280 : status = smb2_create(tree, tctx, &create_io);
164 :
165 1280 : if (!NT_STATUS_IS_OK(status)) {
166 24840 : for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
167 23920 : torture_assert_goto(tctx,
168 : attr_results[l].num != k,
169 : ret, error_exit,
170 : talloc_asprintf(tctx,
171 : "[%d] trunc open 0x%x "
172 : "-> 0x%x of %s failed "
173 : "- should have "
174 : "succeeded !(%s)",
175 : k, open_attrs_table[i],
176 : open_attrs_table[j],
177 : fname,
178 : nt_errstr(status)));
179 : }
180 920 : torture_assert_ntstatus_equal_goto(tctx,
181 : status, NT_STATUS_ACCESS_DENIED,
182 : ret, error_exit,
183 : talloc_asprintf(tctx,
184 : "[%d] trunc open 0x%x "
185 : "-> 0x%x failed with "
186 : "wrong error code %s",
187 : k, open_attrs_table[i],
188 : open_attrs_table[j],
189 : nt_errstr(status)));
190 920 : k++;
191 920 : continue;
192 : }
193 :
194 360 : status = smb2_util_close(tree, create_io.out.file.handle);
195 360 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
196 : error_exit, talloc_asprintf(tctx,
197 : "close %d (2) of %s failed (%s)", j,
198 : fname, nt_errstr(status)));
199 :
200 360 : status = smb2_util_getatr(tree, fname, &attr, NULL, NULL);
201 360 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
202 : error_exit, talloc_asprintf(tctx,
203 : "getatr(2) failed (%s)",
204 : nt_errstr(status)));
205 :
206 7965 : for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
207 7735 : if (attr_results[l].num == k) {
208 130 : if (attr != attr_results[l].result_attr ||
209 130 : open_attrs_table[i] != attr_results[l].init_attr ||
210 130 : open_attrs_table[j] != attr_results[l].trunc_attr) {
211 0 : ret = false;
212 0 : torture_fail_goto(tctx, error_exit,
213 : talloc_asprintf(tctx,
214 : "[%d] getatr check "
215 : "failed. [0x%x] trunc "
216 : "[0x%x] got attr 0x%x,"
217 : " should be 0x%x",
218 : k, open_attrs_table[i],
219 : open_attrs_table[j],
220 : (unsigned int)attr,
221 : attr_results[l].result_attr));
222 : }
223 130 : break;
224 : }
225 : }
226 360 : k++;
227 : }
228 : }
229 5 : error_exit:
230 5 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
231 5 : smb2_util_unlink(tree, fname);
232 :
233 :
234 5 : return ret;
235 : }
236 :
237 5 : bool torture_smb2_winattrtest(struct torture_context *tctx,
238 : struct smb2_tree *tree)
239 : {
240 5 : const char *fname = "winattr1.file";
241 5 : const char *dname = "winattr1.dir";
242 0 : uint16_t attr;
243 0 : uint16_t j;
244 0 : uint32_t aceno;
245 5 : bool ret = true;
246 0 : union smb_fileinfo query, query_org;
247 0 : NTSTATUS status;
248 5 : struct security_descriptor *sd1 = NULL, *sd2 = NULL;
249 5 : struct smb2_create create_io = {0};
250 5 : ZERO_STRUCT(query);
251 5 : ZERO_STRUCT(query_org);
252 :
253 : /* Test winattrs for file */
254 5 : smb2_util_unlink(tree, fname);
255 :
256 : /* Open a file*/
257 5 : create_io.in.create_flags = 0;
258 5 : create_io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA |
259 : SEC_STD_READ_CONTROL;
260 5 : create_io.in.file_attributes = 0;
261 5 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
262 5 : create_io.in.create_disposition = FILE_SUPERSEDE;
263 5 : create_io.in.create_options = 0;
264 5 : create_io.in.security_flags = 0;
265 5 : create_io.in.fname = fname;
266 5 : status = smb2_create(tree, tctx, &create_io);
267 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
268 : talloc_asprintf(tctx, "open(1) of %s failed (%s)\n",
269 : fname, nt_errstr(status)));
270 :
271 : /* Get security descriptor and store it*/
272 5 : query_org.generic.level = RAW_FILEINFO_SEC_DESC;
273 5 : query_org.generic.in.file.handle = create_io.out.file.handle;
274 5 : query_org.query_secdesc.in.secinfo_flags = SECINFO_OWNER|
275 : SECINFO_GROUP|
276 : SECINFO_DACL;
277 5 : status = smb2_getinfo_file(tree, tctx, &query_org);
278 5 : if(!NT_STATUS_IS_OK(status)){
279 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
280 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
281 : talloc_asprintf(tctx,
282 : "close(1) of %s failed (%s)\n",
283 : fname, nt_errstr(s)));
284 0 : ret = false;
285 0 : torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
286 : "smb2_getinfo_file(1) of %s failed (%s)\n",
287 : fname, nt_errstr(status)));
288 : }
289 5 : sd1 = query_org.query_secdesc.out.sd;
290 :
291 5 : status = smb2_util_close(tree, create_io.out.file.handle);
292 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
293 : talloc_asprintf(tctx, "close(1) of %s failed (%s)\n",
294 : fname, nt_errstr(status)));
295 :
296 : /*Set and get attributes*/
297 85 : for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
298 80 : status = smb2_setatr(tree, fname, open_attrs_table[j]);
299 80 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
300 : error_exit,
301 : talloc_asprintf(tctx, "setatr(2) failed (%s)",
302 : nt_errstr(status)));
303 :
304 80 : status = smb2_util_getatr(tree, fname, &attr, NULL, NULL);
305 80 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
306 : error_exit,
307 : talloc_asprintf(tctx, "getatr(2) failed (%s)",
308 : nt_errstr(status)));
309 :
310 : /* Check the result */
311 80 : torture_assert_goto(tctx, attr == open_attrs_table[j], ret,
312 : error_exit, talloc_asprintf(tctx,
313 : "getatr check failed. \
314 : Attr applied [0x%x],got attr 0x%x, \
315 : should be 0x%x ", open_attrs_table[j],
316 : (uint16_t)attr, open_attrs_table[j]));
317 :
318 80 : create_io = (struct smb2_create){0};
319 80 : create_io.in.create_flags = 0;
320 80 : create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE|
321 : SEC_STD_READ_CONTROL;
322 80 : create_io.in.file_attributes = 0;
323 80 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
324 80 : create_io.in.create_disposition = FILE_OPEN_IF;
325 80 : create_io.in.create_options = 0;
326 80 : create_io.in.security_flags = 0;
327 80 : create_io.in.fname = fname;
328 80 : status = smb2_create(tree, tctx, &create_io);
329 80 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
330 : error_exit,
331 : talloc_asprintf(tctx, "open(2) of %s failed (%s)\n",
332 : fname, nt_errstr(status)));
333 : /*Get security descriptor */
334 80 : query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
335 80 : query.query_secdesc.in.file.handle = create_io.out.file.handle;
336 80 : query.query_secdesc.in.secinfo_flags = SECINFO_OWNER|
337 : SECINFO_GROUP|
338 : SECINFO_DACL;
339 80 : status = smb2_getinfo_file(tree, tctx, &query);
340 80 : if(!NT_STATUS_IS_OK(status)){
341 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
342 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret,
343 : error_exit,
344 : talloc_asprintf(tctx,
345 : "close(2) of %s failed (%s)\n",
346 : fname, nt_errstr(s)));
347 0 : ret = false;
348 0 : torture_fail_goto(tctx, error_exit,
349 : talloc_asprintf(tctx,
350 : "smb2_getinfo_file(2) of %s failed (%s)\n",
351 : fname, nt_errstr(status)));
352 : }
353 80 : sd2 = query.query_secdesc.out.sd;
354 :
355 80 : status = smb2_util_close(tree, create_io.out.file.handle);
356 80 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
357 : talloc_asprintf(tctx, "close(2) of %s failed (%s)\n",
358 : fname, nt_errstr(status)));
359 :
360 : /*Compare security descriptors -- Must be same*/
361 336 : for (aceno=0;(sd1->dacl&&aceno < sd1->dacl->num_aces);aceno++){
362 256 : struct security_ace *ace1 = &sd1->dacl->aces[aceno];
363 256 : struct security_ace *ace2 = &sd2->dacl->aces[aceno];
364 :
365 256 : torture_assert_goto(tctx, security_ace_equal(ace1, ace2),
366 : ret, error_exit,
367 : "ACLs changed! Not expected!\n");
368 : }
369 :
370 80 : torture_comment(tctx, "[%d] setattr = [0x%x] got attr 0x%x\n",
371 80 : j, open_attrs_table[j], attr );
372 :
373 : }
374 :
375 :
376 : /* Check for Directory. */
377 :
378 5 : smb2_deltree(tree, dname);
379 5 : smb2_util_rmdir(tree, dname);
380 :
381 : /* Open a directory */
382 5 : create_io = (struct smb2_create){0};
383 5 : create_io.in.create_flags = 0;
384 5 : create_io.in.desired_access = SEC_RIGHTS_DIR_ALL;
385 5 : create_io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
386 5 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
387 5 : create_io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
388 5 : create_io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
389 5 : create_io.in.security_flags = 0;
390 5 : create_io.in.fname = dname;
391 5 : status = smb2_create(tree, tctx, &create_io);
392 :
393 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
394 : talloc_asprintf(tctx,
395 : "open (1) of %s failed (%s)",
396 : dname, nt_errstr(status)));
397 :
398 :
399 : /* Get Security Descriptor */
400 5 : query_org.generic.level = RAW_FILEINFO_SEC_DESC;
401 5 : query_org.generic.in.file.handle = create_io.out.file.handle;
402 5 : status = smb2_getinfo_file(tree, tctx, &query_org);
403 5 : if(!NT_STATUS_IS_OK(status)){
404 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
405 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
406 : talloc_asprintf(tctx,
407 : "close(1) of %s failed (%s)\n",
408 : dname, nt_errstr(s)));
409 0 : ret = false;
410 0 : torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
411 : "smb2_getinfo_file(1) of %s failed (%s)\n", dname,
412 : nt_errstr(status)));
413 : }
414 5 : sd1 = query_org.query_secdesc.out.sd;
415 :
416 5 : status = smb2_util_close(tree, create_io.out.file.handle);
417 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
418 : talloc_asprintf(tctx,
419 : "close (1) of %s failed (%s)", dname,
420 : nt_errstr(status)));
421 :
422 : /* Set and get win attributes*/
423 80 : for (j = 1; j < ARRAY_SIZE(open_attrs_table); j++) {
424 :
425 75 : status = smb2_setatr(tree, dname, open_attrs_table[j]);
426 75 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
427 : talloc_asprintf(tctx, "setatr(2) failed (%s)",
428 : nt_errstr(status)));
429 :
430 75 : status = smb2_util_getatr(tree, dname, &attr, NULL, NULL);
431 75 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
432 : talloc_asprintf(tctx, "getatr(2) failed (%s)",
433 : nt_errstr(status)));
434 :
435 75 : torture_comment(tctx, "[%d] setatt = [0x%x] got attr 0x%x\n",
436 75 : j, open_attrs_table[j], attr );
437 :
438 : /* Check the result */
439 75 : torture_assert_goto(tctx,
440 : attr == (open_attrs_table[j]|FILE_ATTRIBUTE_DIRECTORY),
441 : ret, error_exit, talloc_asprintf(tctx,
442 : "getatr check failed. set attr "
443 : "[0x%x], got attr 0x%x, should be 0x%x\n",
444 : open_attrs_table[j], (uint16_t)attr,
445 : (unsigned int)(open_attrs_table[j]|FILE_ATTRIBUTE_DIRECTORY)));
446 :
447 75 : create_io = (struct smb2_create){0};
448 75 : create_io.in.create_flags = 0;
449 75 : create_io.in.desired_access = SEC_RIGHTS_DIR_READ;
450 75 : create_io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
451 75 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
452 75 : create_io.in.create_disposition = NTCREATEX_DISP_OPEN;
453 75 : create_io.in.create_options = 0;
454 75 : create_io.in.security_flags = 0;
455 75 : create_io.in.fname = dname;
456 75 : status = smb2_create(tree, tctx, &create_io);
457 :
458 75 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
459 : talloc_asprintf(tctx,
460 : "open (2) of %s failed (%s)",
461 : dname, nt_errstr(status)));
462 : /* Get security descriptor */
463 75 : query.generic.level = RAW_FILEINFO_SEC_DESC;
464 75 : query.generic.in.file.handle = create_io.out.file.handle;
465 75 : status = smb2_getinfo_file(tree, tctx, &query);
466 75 : if(!NT_STATUS_IS_OK(status)){
467 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
468 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
469 : talloc_asprintf(tctx,
470 : "close (2) of %s failed (%s)", dname,
471 : nt_errstr(s)));
472 0 : ret = false;
473 0 : torture_fail_goto(tctx, error_exit,
474 : talloc_asprintf(tctx,
475 : "smb2_getinfo_file(2) of %s failed(%s)\n",
476 : dname, nt_errstr(status)));
477 : }
478 75 : sd2 = query.query_secdesc.out.sd;
479 75 : status = smb2_util_close(tree, create_io.out.file.handle);
480 75 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
481 : talloc_asprintf(tctx,
482 : "close (2) of %s failed (%s)", dname,
483 : nt_errstr(status)));
484 :
485 : /* Security descriptor must be same*/
486 435 : for (aceno=0;(sd1->dacl&&aceno < sd1->dacl->num_aces);aceno++){
487 360 : struct security_ace *ace1 = &sd1->dacl->aces[aceno];
488 360 : struct security_ace *ace2 = &sd2->dacl->aces[aceno];
489 :
490 360 : torture_assert_goto(tctx, security_ace_equal(ace1, ace2),
491 : ret, error_exit,
492 : "ACLs changed! Not expected!\n");
493 : }
494 :
495 : }
496 :
497 5 : error_exit:
498 5 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
499 5 : smb2_util_unlink(tree, fname);
500 5 : smb2_deltree(tree, dname);
501 5 : smb2_util_rmdir(tree, dname);
502 :
503 5 : return ret;
504 : }
505 :
506 5 : bool torture_smb2_winattr2(struct torture_context *tctx,
507 : struct smb2_tree *tree)
508 : {
509 5 : const char *fname = "winattr2.file";
510 5 : struct smb2_create c = {0};
511 0 : NTSTATUS status;
512 5 : bool ret = true;
513 :
514 5 : smb2_util_unlink(tree, fname);
515 :
516 : /* Create a file with FILE_ATTRIBUTE_ARCHIVE */
517 5 : c = (struct smb2_create) {
518 : .in.desired_access = SEC_FILE_READ_DATA,
519 : .in.file_attributes = FILE_ATTRIBUTE_ARCHIVE,
520 : .in.share_access = NTCREATEX_SHARE_ACCESS_NONE,
521 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
522 : .in.fname = fname,
523 : };
524 :
525 5 : status = smb2_create(tree, tctx, &c);
526 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
527 : "smb2_create failed\n");
528 :
529 5 : status = smb2_util_close(tree, c.out.file.handle);
530 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
531 : "smb2_util_close failed\n");
532 :
533 : /* Reopen file with different attributes */
534 5 : c = (struct smb2_create) {
535 : .in.desired_access = SEC_FILE_READ_DATA,
536 : .in.file_attributes = FILE_ATTRIBUTE_ARCHIVE |
537 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN |
538 : FILE_ATTRIBUTE_READONLY,
539 : .in.share_access = NTCREATEX_SHARE_ACCESS_NONE,
540 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
541 : .in.fname = fname,
542 : };
543 :
544 5 : status = smb2_create(tree, tctx, &c);
545 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
546 : "smb2_create failed\n");
547 :
548 5 : status = smb2_util_close(tree, c.out.file.handle);
549 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
550 : "smb2_util_close failed\n");
551 :
552 5 : torture_assert_int_equal_goto(tctx,
553 : c.out.file_attr,
554 : FILE_ATTRIBUTE_ARCHIVE,
555 : ret, done,
556 : "Wrong attributes\n");
557 :
558 5 : done:
559 5 : smb2_util_unlink(tree, fname);
560 5 : return ret;
561 : }
562 :
563 4 : bool torture_smb2_sdreadtest(struct torture_context *tctx,
564 : struct smb2_tree *tree)
565 : {
566 4 : const char *fname = "sdread.file";
567 4 : bool ret = true;
568 0 : union smb_fileinfo query;
569 0 : NTSTATUS status;
570 4 : struct security_descriptor *sd = NULL;
571 4 : struct smb2_create create_io = {0};
572 4 : uint32_t sd_bits[] = { SECINFO_OWNER,
573 : SECINFO_GROUP,
574 : SECINFO_DACL };
575 0 : size_t i;
576 :
577 4 : ZERO_STRUCT(query);
578 :
579 4 : smb2_util_unlink(tree, fname);
580 :
581 : /* Create then close a file*/
582 4 : create_io.in.create_flags = 0;
583 4 : create_io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
584 4 : create_io.in.file_attributes = 0;
585 4 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
586 4 : create_io.in.create_disposition = FILE_SUPERSEDE;
587 4 : create_io.in.create_options = 0;
588 4 : create_io.in.security_flags = 0;
589 4 : create_io.in.fname = fname;
590 4 : status = smb2_create(tree, tctx, &create_io);
591 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
592 : talloc_asprintf(tctx, "open(1) of %s failed (%s)\n",
593 : fname, nt_errstr(status)));
594 4 : status = smb2_util_close(tree, create_io.out.file.handle);
595 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
596 : talloc_asprintf(tctx, "close(1) of %s failed (%s)\n",
597 : fname, nt_errstr(status)));
598 :
599 : /*
600 : * Open the file with READ_ATTRIBUTES *only*,
601 : * no READ_CONTROL.
602 : *
603 : * This should deny access for any attempt to
604 : * get a security descriptor if we ask for
605 : * any of OWNER|GROUP|DACL, but if
606 : * we ask for *NO* info but still ask for
607 : * the security descriptor, then Windows
608 : * returns an ACL but with zero entries
609 : * for OWNER|GROUP|DACL.
610 : */
611 :
612 4 : create_io = (struct smb2_create){0};
613 4 : create_io.in.create_flags = 0;
614 4 : create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
615 4 : create_io.in.file_attributes = 0;
616 4 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
617 4 : create_io.in.create_disposition = FILE_OPEN;
618 4 : create_io.in.create_options = 0;
619 4 : create_io.in.security_flags = 0;
620 4 : create_io.in.fname = fname;
621 4 : status = smb2_create(tree, tctx, &create_io);
622 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
623 : error_exit,
624 : talloc_asprintf(tctx, "open(2) of %s failed (%s)\n",
625 : fname, nt_errstr(status)));
626 :
627 : /* Check asking for SD fails ACCESS_DENIED with actual bits set. */
628 16 : for (i = 0; i < ARRAY_SIZE(sd_bits); i++) {
629 12 : query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
630 12 : query.query_secdesc.in.file.handle = create_io.out.file.handle;
631 12 : query.query_secdesc.in.secinfo_flags = sd_bits[i];
632 :
633 12 : status = smb2_getinfo_file(tree, tctx, &query);
634 :
635 : /* Must return ACESS_DENIED. */
636 12 : if(!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)){
637 0 : NTSTATUS s = smb2_util_close(tree,
638 : create_io.out.file.handle);
639 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret,
640 : error_exit,
641 : talloc_asprintf(tctx,
642 : "close(2) of %s failed (%s)\n",
643 : fname, nt_errstr(s)));
644 0 : ret = false;
645 0 : torture_fail_goto(tctx, error_exit,
646 : talloc_asprintf(tctx,
647 : "smb2_getinfo_file(2) of %s failed (%s)\n",
648 : fname, nt_errstr(status)));
649 : }
650 : }
651 :
652 : /*
653 : * Get security descriptor whilst asking for *NO* bits.
654 : * This succeeds even though we don't have READ_CONTROL
655 : * access but returns an SD with zero data.
656 : */
657 4 : query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
658 4 : query.query_secdesc.in.file.handle = create_io.out.file.handle;
659 4 : query.query_secdesc.in.secinfo_flags = 0;
660 :
661 4 : status = smb2_getinfo_file(tree, tctx, &query);
662 4 : if(!NT_STATUS_IS_OK(status)){
663 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
664 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
665 : talloc_asprintf(tctx,
666 : "close(3) of %s failed (%s)\n",
667 : fname, nt_errstr(s)));
668 0 : ret = false;
669 0 : torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
670 : "smb2_getinfo_file(3) of %s failed (%s)\n",
671 : fname, nt_errstr(status)));
672 : }
673 :
674 4 : sd = query.query_secdesc.out.sd;
675 :
676 : /* Check it's empty. */
677 4 : torture_assert_goto(tctx,
678 : (sd->owner_sid == NULL),
679 : ret,
680 : error_exit,
681 : "sd->owner_sid != NULL\n");
682 :
683 4 : torture_assert_goto(tctx,
684 : (sd->group_sid == NULL),
685 : ret,
686 : error_exit,
687 : "sd->group_sid != NULL\n");
688 :
689 4 : torture_assert_goto(tctx,
690 : (sd->dacl == NULL),
691 : ret,
692 : error_exit,
693 : "sd->dacl != NULL\n");
694 :
695 4 : status = smb2_util_close(tree, create_io.out.file.handle);
696 4 : torture_assert_ntstatus_ok_goto(tctx,
697 : status,
698 : ret,
699 : error_exit,
700 : talloc_asprintf(tctx, "close(4) of %s failed (%s)\n",
701 : fname,
702 : nt_errstr(status)));
703 :
704 4 : error_exit:
705 :
706 4 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
707 4 : smb2_util_unlink(tree, fname);
708 :
709 4 : return ret;
710 : }
|