libads: Make ads_cldap_netlogon() static
[samba4-gss.git] / source4 / torture / smb2 / attr.c
blobbc474d29cfa1a0d943a1eb81063992bd210f2c52
1 /*
2 Unix SMB/CIFS implementation.
4 openattr tester
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/>.
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"
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 {
51 unsigned int num;
52 uint32_t init_attr;
53 uint32_t trunc_attr;
54 uint32_t result_attr;
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,
87 uint32_t attrib)
89 NTSTATUS status;
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)) {
101 return status;
104 ZERO_STRUCT(io);
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)) {
110 return status;
113 status = smb2_util_close(tree, create_io.out.file.handle);
114 if (!NT_STATUS_IS_OK(status)) {
115 return status;
118 return status;
121 bool torture_smb2_openattrtest(struct torture_context *tctx,
122 struct smb2_tree *tree)
124 NTSTATUS status;
125 const char *fname = "openattr.file";
126 uint16_t attr;
127 unsigned int i, j, k, l;
128 int ret = true;
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|
156 SEC_FILE_WRITE_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,
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)));
180 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 k++;
191 continue;
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)",
204 nt_errstr(status)));
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) {
211 ret = false;
212 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));
223 break;
226 k++;
229 error_exit:
230 smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
231 smb2_util_unlink(tree, fname);
234 return ret;
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";
242 uint16_t attr;
243 uint16_t j;
244 uint32_t aceno;
245 bool ret = true;
246 union smb_fileinfo query, query_org;
247 NTSTATUS status;
248 struct security_descriptor *sd1 = NULL, *sd2 = NULL;
249 struct smb2_create create_io = {0};
250 ZERO_STRUCT(query);
251 ZERO_STRUCT(query_org);
253 /* Test winattrs for file */
254 smb2_util_unlink(tree, fname);
256 /* Open a file*/
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|
275 SECINFO_GROUP|
276 SECINFO_DACL;
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)));
284 ret = false;
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,
300 error_exit,
301 talloc_asprintf(tctx, "setatr(2) failed (%s)",
302 nt_errstr(status)));
304 status = smb2_util_getatr(tree, fname, &attr, NULL, NULL);
305 torture_assert_ntstatus_ok_goto(tctx, status, ret,
306 error_exit,
307 talloc_asprintf(tctx, "getatr(2) failed (%s)",
308 nt_errstr(status)));
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,
330 error_exit,
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|
337 SECINFO_GROUP|
338 SECINFO_DACL;
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,
343 error_exit,
344 talloc_asprintf(tctx,
345 "close(2) of %s failed (%s)\n",
346 fname, nt_errstr(s)));
347 ret = false;
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),
366 ret, error_exit,
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)));
409 ret = false;
410 torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
411 "smb2_getinfo_file(1) of %s failed (%s)\n", dname,
412 nt_errstr(status)));
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,
420 nt_errstr(status)));
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)",
428 nt_errstr(status)));
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)",
433 nt_errstr(status)));
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,
471 nt_errstr(s)));
472 ret = false;
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,
483 nt_errstr(status)));
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),
491 ret, error_exit,
492 "ACLs changed! Not expected!\n");
497 error_exit:
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);
503 return ret;
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};
511 NTSTATUS status;
512 bool ret = true;
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,
522 .in.fname = fname,
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,
541 .in.fname = fname,
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,
553 c.out.file_attr,
554 FILE_ATTRIBUTE_ARCHIVE,
555 ret, done,
556 "Wrong attributes\n");
558 done:
559 smb2_util_unlink(tree, fname);
560 return ret;
563 bool torture_smb2_sdreadtest(struct torture_context *tctx,
564 struct smb2_tree *tree)
566 const char *fname = "sdread.file";
567 bool ret = true;
568 union smb_fileinfo query;
569 NTSTATUS status;
570 struct security_descriptor *sd = NULL;
571 struct smb2_create create_io = {0};
572 uint32_t sd_bits[] = { SECINFO_OWNER,
573 SECINFO_GROUP,
574 SECINFO_DACL };
575 size_t i;
577 ZERO_STRUCT(query);
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*,
601 * no READ_CONTROL.
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,
623 error_exit,
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,
640 error_exit,
641 talloc_asprintf(tctx,
642 "close(2) of %s failed (%s)\n",
643 fname, nt_errstr(s)));
644 ret = false;
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)));
668 ret = false;
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),
679 ret,
680 error_exit,
681 "sd->owner_sid != NULL\n");
683 torture_assert_goto(tctx,
684 (sd->group_sid == NULL),
685 ret,
686 error_exit,
687 "sd->group_sid != NULL\n");
689 torture_assert_goto(tctx,
690 (sd->dacl == NULL),
691 ret,
692 error_exit,
693 "sd->dacl != NULL\n");
695 status = smb2_util_close(tree, create_io.out.file.handle);
696 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)));
704 error_exit:
706 smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
707 smb2_util_unlink(tree, fname);
709 return ret;