2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) David Mulder 2019
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.
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.
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/>.
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"
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
,
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
,
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
,
50 struct trunc_open_results
{
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
}
86 static NTSTATUS
smb2_setatr(struct smb2_tree
*tree
, const char *name
,
90 struct smb2_create create_io
= {0};
91 union smb_setfileinfo io
;
93 create_io
.in
.desired_access
= SEC_FILE_READ_DATA
|
94 SEC_FILE_WRITE_ATTRIBUTE
;
95 create_io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
96 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
97 create_io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
98 create_io
.in
.fname
= name
;
99 status
= smb2_create(tree
, tree
, &create_io
);
100 if (!NT_STATUS_IS_OK(status
)) {
105 io
.basic_info
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
106 io
.basic_info
.in
.file
.handle
= create_io
.out
.file
.handle
;
107 io
.basic_info
.in
.attrib
= attrib
;
108 status
= smb2_setinfo_file(tree
, &io
);
109 if (!NT_STATUS_IS_OK(status
)) {
113 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
114 if (!NT_STATUS_IS_OK(status
)) {
121 bool torture_smb2_openattrtest(struct torture_context
*tctx
,
122 struct smb2_tree
*tree
)
125 const char *fname
= "openattr.file";
127 unsigned int i
, j
, k
, l
;
130 for (k
= 0, i
= 0; i
< sizeof(open_attrs_table
)/sizeof(uint32_t); i
++) {
131 struct smb2_create create_io
= {0};
132 smb2_setatr(tree
, fname
, FILE_ATTRIBUTE_NORMAL
);
133 smb2_util_unlink(tree
, fname
);
134 create_io
.in
.create_flags
= 0;
135 create_io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
136 create_io
.in
.file_attributes
= open_attrs_table
[i
];
137 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
138 create_io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
139 create_io
.in
.create_options
= 0;
140 create_io
.in
.security_flags
= 0;
141 create_io
.in
.fname
= fname
;
142 status
= smb2_create(tree
, tctx
, &create_io
);
143 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
)));
147 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
148 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
)));
152 for (j
= 0; j
< ARRAY_SIZE(open_attrs_table
); j
++) {
153 create_io
= (struct smb2_create
){0};
154 create_io
.in
.create_flags
= 0;
155 create_io
.in
.desired_access
= SEC_FILE_READ_DATA
|
157 create_io
.in
.file_attributes
= open_attrs_table
[j
];
158 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
159 create_io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE
;
160 create_io
.in
.create_options
= 0;
161 create_io
.in
.security_flags
= 0;
162 create_io
.in
.fname
= fname
;
163 status
= smb2_create(tree
, tctx
, &create_io
);
165 if (!NT_STATUS_IS_OK(status
)) {
166 for (l
= 0; l
< ARRAY_SIZE(attr_results
); l
++) {
167 torture_assert_goto(tctx
,
168 attr_results
[l
].num
!= k
,
170 talloc_asprintf(tctx
,
171 "[%d] trunc open 0x%x "
172 "-> 0x%x of %s failed "
175 k
, open_attrs_table
[i
],
180 torture_assert_ntstatus_equal_goto(tctx
,
181 status
, NT_STATUS_ACCESS_DENIED
,
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
],
194 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
195 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
)));
200 status
= smb2_util_getatr(tree
, fname
, &attr
, NULL
, NULL
);
201 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
,
202 error_exit
, talloc_asprintf(tctx
,
203 "getatr(2) failed (%s)",
206 for (l
= 0; l
< ARRAY_SIZE(attr_results
); l
++) {
207 if (attr_results
[l
].num
== k
) {
208 if (attr
!= attr_results
[l
].result_attr
||
209 open_attrs_table
[i
] != attr_results
[l
].init_attr
||
210 open_attrs_table
[j
] != attr_results
[l
].trunc_attr
) {
212 torture_fail_goto(tctx
, error_exit
,
213 talloc_asprintf(tctx
,
215 "failed. [0x%x] trunc "
216 "[0x%x] got attr 0x%x,"
218 k
, open_attrs_table
[i
],
221 attr_results
[l
].result_attr
));
230 smb2_setatr(tree
, fname
, FILE_ATTRIBUTE_NORMAL
);
231 smb2_util_unlink(tree
, fname
);
237 bool torture_smb2_winattrtest(struct torture_context
*tctx
,
238 struct smb2_tree
*tree
)
240 const char *fname
= "winattr1.file";
241 const char *dname
= "winattr1.dir";
246 union smb_fileinfo query
, query_org
;
248 struct security_descriptor
*sd1
= NULL
, *sd2
= NULL
;
249 struct smb2_create create_io
= {0};
251 ZERO_STRUCT(query_org
);
253 /* Test winattrs for file */
254 smb2_util_unlink(tree
, fname
);
257 create_io
.in
.create_flags
= 0;
258 create_io
.in
.desired_access
= SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
|
259 SEC_STD_READ_CONTROL
;
260 create_io
.in
.file_attributes
= 0;
261 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
262 create_io
.in
.create_disposition
= FILE_SUPERSEDE
;
263 create_io
.in
.create_options
= 0;
264 create_io
.in
.security_flags
= 0;
265 create_io
.in
.fname
= fname
;
266 status
= smb2_create(tree
, tctx
, &create_io
);
267 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
)));
271 /* Get security descriptor and store it*/
272 query_org
.generic
.level
= RAW_FILEINFO_SEC_DESC
;
273 query_org
.generic
.in
.file
.handle
= create_io
.out
.file
.handle
;
274 query_org
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
|
277 status
= smb2_getinfo_file(tree
, tctx
, &query_org
);
278 if(!NT_STATUS_IS_OK(status
)){
279 NTSTATUS s
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
280 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
)));
285 torture_fail_goto(tctx
, error_exit
, talloc_asprintf(tctx
,
286 "smb2_getinfo_file(1) of %s failed (%s)\n",
287 fname
, nt_errstr(status
)));
289 sd1
= query_org
.query_secdesc
.out
.sd
;
291 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
292 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
)));
296 /*Set and get attributes*/
297 for (j
= 0; j
< ARRAY_SIZE(open_attrs_table
); j
++) {
298 status
= smb2_setatr(tree
, fname
, open_attrs_table
[j
]);
299 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
,
301 talloc_asprintf(tctx
, "setatr(2) failed (%s)",
304 status
= smb2_util_getatr(tree
, fname
, &attr
, NULL
, NULL
);
305 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
,
307 talloc_asprintf(tctx
, "getatr(2) failed (%s)",
310 /* Check the result */
311 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
]));
318 create_io
= (struct smb2_create
){0};
319 create_io
.in
.create_flags
= 0;
320 create_io
.in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
|
321 SEC_STD_READ_CONTROL
;
322 create_io
.in
.file_attributes
= 0;
323 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
324 create_io
.in
.create_disposition
= FILE_OPEN_IF
;
325 create_io
.in
.create_options
= 0;
326 create_io
.in
.security_flags
= 0;
327 create_io
.in
.fname
= fname
;
328 status
= smb2_create(tree
, tctx
, &create_io
);
329 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
,
331 talloc_asprintf(tctx
, "open(2) of %s failed (%s)\n",
332 fname
, nt_errstr(status
)));
333 /*Get security descriptor */
334 query
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
335 query
.query_secdesc
.in
.file
.handle
= create_io
.out
.file
.handle
;
336 query
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
|
339 status
= smb2_getinfo_file(tree
, tctx
, &query
);
340 if(!NT_STATUS_IS_OK(status
)){
341 NTSTATUS s
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
342 torture_assert_ntstatus_ok_goto(tctx
, s
, ret
,
344 talloc_asprintf(tctx
,
345 "close(2) of %s failed (%s)\n",
346 fname
, nt_errstr(s
)));
348 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
)));
353 sd2
= query
.query_secdesc
.out
.sd
;
355 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
356 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
)));
360 /*Compare security descriptors -- Must be same*/
361 for (aceno
=0;(sd1
->dacl
&&aceno
< sd1
->dacl
->num_aces
);aceno
++){
362 struct security_ace
*ace1
= &sd1
->dacl
->aces
[aceno
];
363 struct security_ace
*ace2
= &sd2
->dacl
->aces
[aceno
];
365 torture_assert_goto(tctx
, security_ace_equal(ace1
, ace2
),
367 "ACLs changed! Not expected!\n");
370 torture_comment(tctx
, "[%d] setattr = [0x%x] got attr 0x%x\n",
371 j
, open_attrs_table
[j
], attr
);
376 /* Check for Directory. */
378 smb2_deltree(tree
, dname
);
379 smb2_util_rmdir(tree
, dname
);
381 /* Open a directory */
382 create_io
= (struct smb2_create
){0};
383 create_io
.in
.create_flags
= 0;
384 create_io
.in
.desired_access
= SEC_RIGHTS_DIR_ALL
;
385 create_io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
386 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
387 create_io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
388 create_io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
389 create_io
.in
.security_flags
= 0;
390 create_io
.in
.fname
= dname
;
391 status
= smb2_create(tree
, tctx
, &create_io
);
393 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
)));
399 /* Get Security Descriptor */
400 query_org
.generic
.level
= RAW_FILEINFO_SEC_DESC
;
401 query_org
.generic
.in
.file
.handle
= create_io
.out
.file
.handle
;
402 status
= smb2_getinfo_file(tree
, tctx
, &query_org
);
403 if(!NT_STATUS_IS_OK(status
)){
404 NTSTATUS s
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
405 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
)));
410 torture_fail_goto(tctx
, error_exit
, talloc_asprintf(tctx
,
411 "smb2_getinfo_file(1) of %s failed (%s)\n", dname
,
414 sd1
= query_org
.query_secdesc
.out
.sd
;
416 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
417 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, error_exit
,
418 talloc_asprintf(tctx
,
419 "close (1) of %s failed (%s)", dname
,
422 /* Set and get win attributes*/
423 for (j
= 1; j
< ARRAY_SIZE(open_attrs_table
); j
++) {
425 status
= smb2_setatr(tree
, dname
, open_attrs_table
[j
]);
426 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, error_exit
,
427 talloc_asprintf(tctx
, "setatr(2) failed (%s)",
430 status
= smb2_util_getatr(tree
, dname
, &attr
, NULL
, NULL
);
431 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, error_exit
,
432 talloc_asprintf(tctx
, "getatr(2) failed (%s)",
435 torture_comment(tctx
, "[%d] setatt = [0x%x] got attr 0x%x\n",
436 j
, open_attrs_table
[j
], attr
);
438 /* Check the result */
439 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
)));
447 create_io
= (struct smb2_create
){0};
448 create_io
.in
.create_flags
= 0;
449 create_io
.in
.desired_access
= SEC_RIGHTS_DIR_READ
;
450 create_io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
451 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
452 create_io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
453 create_io
.in
.create_options
= 0;
454 create_io
.in
.security_flags
= 0;
455 create_io
.in
.fname
= dname
;
456 status
= smb2_create(tree
, tctx
, &create_io
);
458 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 query
.generic
.level
= RAW_FILEINFO_SEC_DESC
;
464 query
.generic
.in
.file
.handle
= create_io
.out
.file
.handle
;
465 status
= smb2_getinfo_file(tree
, tctx
, &query
);
466 if(!NT_STATUS_IS_OK(status
)){
467 NTSTATUS s
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
468 torture_assert_ntstatus_ok_goto(tctx
, s
, ret
, error_exit
,
469 talloc_asprintf(tctx
,
470 "close (2) of %s failed (%s)", dname
,
473 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
)));
478 sd2
= query
.query_secdesc
.out
.sd
;
479 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
480 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, error_exit
,
481 talloc_asprintf(tctx
,
482 "close (2) of %s failed (%s)", dname
,
485 /* Security descriptor must be same*/
486 for (aceno
=0;(sd1
->dacl
&&aceno
< sd1
->dacl
->num_aces
);aceno
++){
487 struct security_ace
*ace1
= &sd1
->dacl
->aces
[aceno
];
488 struct security_ace
*ace2
= &sd2
->dacl
->aces
[aceno
];
490 torture_assert_goto(tctx
, security_ace_equal(ace1
, ace2
),
492 "ACLs changed! Not expected!\n");
498 smb2_setatr(tree
, fname
, FILE_ATTRIBUTE_NORMAL
);
499 smb2_util_unlink(tree
, fname
);
500 smb2_deltree(tree
, dname
);
501 smb2_util_rmdir(tree
, dname
);
506 bool torture_smb2_winattr2(struct torture_context
*tctx
,
507 struct smb2_tree
*tree
)
509 const char *fname
= "winattr2.file";
510 struct smb2_create c
= {0};
514 smb2_util_unlink(tree
, fname
);
516 /* Create a file with FILE_ATTRIBUTE_ARCHIVE */
517 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
,
525 status
= smb2_create(tree
, tctx
, &c
);
526 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
527 "smb2_create failed\n");
529 status
= smb2_util_close(tree
, c
.out
.file
.handle
);
530 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
531 "smb2_util_close failed\n");
533 /* Reopen file with different attributes */
534 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
,
544 status
= smb2_create(tree
, tctx
, &c
);
545 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
546 "smb2_create failed\n");
548 status
= smb2_util_close(tree
, c
.out
.file
.handle
);
549 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
550 "smb2_util_close failed\n");
552 torture_assert_int_equal_goto(tctx
,
554 FILE_ATTRIBUTE_ARCHIVE
,
556 "Wrong attributes\n");
559 smb2_util_unlink(tree
, fname
);
563 bool torture_smb2_sdreadtest(struct torture_context
*tctx
,
564 struct smb2_tree
*tree
)
566 const char *fname
= "sdread.file";
568 union smb_fileinfo query
;
570 struct security_descriptor
*sd
= NULL
;
571 struct smb2_create create_io
= {0};
572 uint32_t sd_bits
[] = { SECINFO_OWNER
,
579 smb2_util_unlink(tree
, fname
);
581 /* Create then close a file*/
582 create_io
.in
.create_flags
= 0;
583 create_io
.in
.desired_access
= SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
584 create_io
.in
.file_attributes
= 0;
585 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
586 create_io
.in
.create_disposition
= FILE_SUPERSEDE
;
587 create_io
.in
.create_options
= 0;
588 create_io
.in
.security_flags
= 0;
589 create_io
.in
.fname
= fname
;
590 status
= smb2_create(tree
, tctx
, &create_io
);
591 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 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
595 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
)));
600 * Open the file with READ_ATTRIBUTES *only*,
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.
612 create_io
= (struct smb2_create
){0};
613 create_io
.in
.create_flags
= 0;
614 create_io
.in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
;
615 create_io
.in
.file_attributes
= 0;
616 create_io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
617 create_io
.in
.create_disposition
= FILE_OPEN
;
618 create_io
.in
.create_options
= 0;
619 create_io
.in
.security_flags
= 0;
620 create_io
.in
.fname
= fname
;
621 status
= smb2_create(tree
, tctx
, &create_io
);
622 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
,
624 talloc_asprintf(tctx
, "open(2) of %s failed (%s)\n",
625 fname
, nt_errstr(status
)));
627 /* Check asking for SD fails ACCESS_DENIED with actual bits set. */
628 for (i
= 0; i
< ARRAY_SIZE(sd_bits
); i
++) {
629 query
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
630 query
.query_secdesc
.in
.file
.handle
= create_io
.out
.file
.handle
;
631 query
.query_secdesc
.in
.secinfo_flags
= sd_bits
[i
];
633 status
= smb2_getinfo_file(tree
, tctx
, &query
);
635 /* Must return ACESS_DENIED. */
636 if(!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)){
637 NTSTATUS s
= smb2_util_close(tree
,
638 create_io
.out
.file
.handle
);
639 torture_assert_ntstatus_ok_goto(tctx
, s
, ret
,
641 talloc_asprintf(tctx
,
642 "close(2) of %s failed (%s)\n",
643 fname
, nt_errstr(s
)));
645 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
)));
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.
657 query
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
658 query
.query_secdesc
.in
.file
.handle
= create_io
.out
.file
.handle
;
659 query
.query_secdesc
.in
.secinfo_flags
= 0;
661 status
= smb2_getinfo_file(tree
, tctx
, &query
);
662 if(!NT_STATUS_IS_OK(status
)){
663 NTSTATUS s
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
664 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
)));
669 torture_fail_goto(tctx
, error_exit
, talloc_asprintf(tctx
,
670 "smb2_getinfo_file(3) of %s failed (%s)\n",
671 fname
, nt_errstr(status
)));
674 sd
= query
.query_secdesc
.out
.sd
;
676 /* Check it's empty. */
677 torture_assert_goto(tctx
,
678 (sd
->owner_sid
== NULL
),
681 "sd->owner_sid != NULL\n");
683 torture_assert_goto(tctx
,
684 (sd
->group_sid
== NULL
),
687 "sd->group_sid != NULL\n");
689 torture_assert_goto(tctx
,
693 "sd->dacl != NULL\n");
695 status
= smb2_util_close(tree
, create_io
.out
.file
.handle
);
696 torture_assert_ntstatus_ok_goto(tctx
,
700 talloc_asprintf(tctx
, "close(4) of %s failed (%s)\n",
706 smb2_setatr(tree
, fname
, FILE_ATTRIBUTE_NORMAL
);
707 smb2_util_unlink(tree
, fname
);