Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : test security descriptor operations for SMB2
5 :
6 : Copyright (C) Zack Kirsch 2009
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 "lib/cmdline/cmdline.h"
24 : #include "libcli/smb2/smb2.h"
25 : #include "libcli/smb2/smb2_calls.h"
26 : #include "libcli/smb/smbXcli_base.h"
27 : #include "torture/torture.h"
28 : #include "libcli/resolve/resolve.h"
29 : #include "torture/util.h"
30 : #include "torture/smb2/proto.h"
31 : #include "libcli/security/security.h"
32 : #include "librpc/gen_ndr/ndr_security.h"
33 : #include "lib/param/param.h"
34 :
35 : #define CHECK_STATUS(status, correct) do { \
36 : if (!NT_STATUS_EQUAL(status, correct)) { \
37 : torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
38 : __location__, nt_errstr(status), nt_errstr(correct)); \
39 : ret = false; \
40 : goto done; \
41 : }} while (0)
42 :
43 : #define BASEDIR "smb2-testsd"
44 :
45 : #define CHECK_ACCESS_IGNORE SEC_STD_SYNCHRONIZE
46 :
47 : #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
48 : union smb_fileinfo _q; \
49 : _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
50 : _q.access_information.in.file.handle = (_fh); \
51 : status = smb2_getinfo_file(tree, tctx, &_q); \
52 : CHECK_STATUS(status, NT_STATUS_OK); \
53 : /* Handle a Vista bug where SEC_STD_SYNCHRONIZE doesn't come back. */ \
54 : if ((((flags) & CHECK_ACCESS_IGNORE) == CHECK_ACCESS_IGNORE) && \
55 : ((_q.access_information.out.access_flags & CHECK_ACCESS_IGNORE) != CHECK_ACCESS_IGNORE)) { \
56 : torture_comment(tctx, "SKIPPING (Vista bug): (%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
57 : __location__, _q.access_information.out.access_flags, (flags)); \
58 : } \
59 : if ((_q.access_information.out.access_flags & ~CHECK_ACCESS_IGNORE) != \
60 : (((flags) & ~CHECK_ACCESS_IGNORE))) { \
61 : torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
62 : __location__, _q.access_information.out.access_flags, (flags)); \
63 : ret = false; \
64 : goto done; \
65 : } \
66 : } while (0)
67 :
68 : #define FAIL_UNLESS(__cond) \
69 : do { \
70 : if (__cond) {} else { \
71 : torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \
72 : __location__, #__cond); \
73 : ret = false; goto done; \
74 : } \
75 : } while(0)
76 :
77 : #define CHECK_SECURITY_DESCRIPTOR(_sd1, _sd2) do { \
78 : if (!security_descriptor_equal(_sd1, _sd2)) { \
79 : torture_warning(tctx, "security descriptors don't match!\n"); \
80 : torture_warning(tctx, "got:\n"); \
81 : NDR_PRINT_DEBUG(security_descriptor, _sd1); \
82 : torture_warning(tctx, "expected:\n"); \
83 : NDR_PRINT_DEBUG(security_descriptor, _sd2); \
84 : torture_result(tctx, TORTURE_FAIL, \
85 : "%s: security descriptors don't match!\n", \
86 : __location__); \
87 : ret = false; \
88 : } \
89 : } while (0)
90 :
91 : /*
92 : test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
93 : mapping bits
94 : Note: This test was copied from raw/acls.c.
95 : */
96 4 : static bool test_creator_sid(struct torture_context *tctx, struct smb2_tree *tree)
97 : {
98 0 : NTSTATUS status;
99 0 : struct smb2_create io;
100 4 : const char *fname = BASEDIR "\\creator.txt";
101 4 : bool ret = true;
102 4 : struct smb2_handle handle = {{0}};
103 0 : union smb_fileinfo q;
104 0 : union smb_setfileinfo set;
105 0 : struct security_descriptor *sd, *sd_orig, *sd2;
106 0 : const char *owner_sid;
107 :
108 4 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
109 0 : return false;
110 :
111 4 : torture_comment(tctx, "TESTING SID_CREATOR_OWNER\n");
112 :
113 4 : ZERO_STRUCT(io);
114 4 : io.level = RAW_OPEN_SMB2;
115 4 : io.in.create_flags = 0;
116 4 : io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER;
117 4 : io.in.create_options = 0;
118 4 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
119 4 : io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
120 : NTCREATEX_SHARE_ACCESS_READ |
121 : NTCREATEX_SHARE_ACCESS_WRITE;
122 4 : io.in.alloc_size = 0;
123 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
124 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
125 4 : io.in.security_flags = 0;
126 4 : io.in.fname = fname;
127 :
128 4 : status = smb2_create(tree, tctx, &io);
129 4 : CHECK_STATUS(status, NT_STATUS_OK);
130 4 : handle = io.out.file.handle;
131 :
132 4 : torture_comment(tctx, "get the original sd\n");
133 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
134 4 : q.query_secdesc.in.file.handle = handle;
135 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
136 4 : status = smb2_getinfo_file(tree, tctx, &q);
137 4 : CHECK_STATUS(status, NT_STATUS_OK);
138 4 : sd_orig = q.query_secdesc.out.sd;
139 :
140 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
141 :
142 4 : torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n");
143 4 : sd = security_descriptor_dacl_create(tctx,
144 : 0, NULL, NULL,
145 : SID_CREATOR_OWNER,
146 : SEC_ACE_TYPE_ACCESS_ALLOWED,
147 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
148 : 0,
149 : NULL);
150 :
151 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
152 4 : set.set_secdesc.in.file.handle = handle;
153 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
154 4 : set.set_secdesc.in.sd = sd;
155 :
156 4 : status = smb2_setinfo_file(tree, &set);
157 4 : CHECK_STATUS(status, NT_STATUS_OK);
158 :
159 4 : torture_comment(tctx, "try open for write\n");
160 4 : io.in.desired_access = SEC_FILE_WRITE_DATA;
161 4 : status = smb2_create(tree, tctx, &io);
162 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
163 :
164 4 : torture_comment(tctx, "try open for read\n");
165 4 : io.in.desired_access = SEC_FILE_READ_DATA;
166 4 : status = smb2_create(tree, tctx, &io);
167 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
168 :
169 4 : torture_comment(tctx, "try open for generic write\n");
170 4 : io.in.desired_access = SEC_GENERIC_WRITE;
171 4 : status = smb2_create(tree, tctx, &io);
172 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
173 :
174 4 : torture_comment(tctx, "try open for generic read\n");
175 4 : io.in.desired_access = SEC_GENERIC_READ;
176 4 : status = smb2_create(tree, tctx, &io);
177 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
178 :
179 4 : torture_comment(tctx, "set a sec desc allowing no write by owner\n");
180 4 : sd = security_descriptor_dacl_create(tctx,
181 : 0, owner_sid, NULL,
182 : owner_sid,
183 : SEC_ACE_TYPE_ACCESS_ALLOWED,
184 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
185 : 0,
186 : NULL);
187 :
188 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
189 4 : set.set_secdesc.in.file.handle = handle;
190 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
191 4 : set.set_secdesc.in.sd = sd;
192 4 : status = smb2_setinfo_file(tree, &set);
193 4 : CHECK_STATUS(status, NT_STATUS_OK);
194 :
195 4 : torture_comment(tctx, "check that sd has been mapped correctly\n");
196 4 : status = smb2_getinfo_file(tree, tctx, &q);
197 4 : CHECK_STATUS(status, NT_STATUS_OK);
198 4 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
199 :
200 4 : torture_comment(tctx, "try open for write\n");
201 4 : io.in.desired_access = SEC_FILE_WRITE_DATA;
202 4 : status = smb2_create(tree, tctx, &io);
203 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
204 :
205 4 : torture_comment(tctx, "try open for read\n");
206 4 : io.in.desired_access = SEC_FILE_READ_DATA;
207 4 : status = smb2_create(tree, tctx, &io);
208 4 : CHECK_STATUS(status, NT_STATUS_OK);
209 8 : CHECK_ACCESS_FLAGS(io.out.file.handle,
210 : SEC_FILE_READ_DATA);
211 4 : smb2_util_close(tree, io.out.file.handle);
212 :
213 4 : torture_comment(tctx, "try open for generic write\n");
214 4 : io.in.desired_access = SEC_GENERIC_WRITE;
215 4 : status = smb2_create(tree, tctx, &io);
216 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
217 :
218 4 : torture_comment(tctx, "try open for generic read\n");
219 4 : io.in.desired_access = SEC_GENERIC_READ;
220 4 : status = smb2_create(tree, tctx, &io);
221 4 : CHECK_STATUS(status, NT_STATUS_OK);
222 4 : CHECK_ACCESS_FLAGS(io.out.file.handle,
223 : SEC_RIGHTS_FILE_READ);
224 4 : smb2_util_close(tree, io.out.file.handle);
225 :
226 4 : torture_comment(tctx, "set a sec desc allowing generic read by owner\n");
227 4 : sd = security_descriptor_dacl_create(tctx,
228 : 0, NULL, NULL,
229 : owner_sid,
230 : SEC_ACE_TYPE_ACCESS_ALLOWED,
231 : SEC_GENERIC_READ | SEC_STD_ALL,
232 : 0,
233 : NULL);
234 :
235 4 : set.set_secdesc.in.sd = sd;
236 4 : status = smb2_setinfo_file(tree, &set);
237 4 : CHECK_STATUS(status, NT_STATUS_OK);
238 :
239 4 : torture_comment(tctx, "check that generic read has been mapped correctly\n");
240 4 : sd2 = security_descriptor_dacl_create(tctx,
241 : 0, owner_sid, NULL,
242 : owner_sid,
243 : SEC_ACE_TYPE_ACCESS_ALLOWED,
244 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
245 : 0,
246 : NULL);
247 :
248 4 : status = smb2_getinfo_file(tree, tctx, &q);
249 4 : CHECK_STATUS(status, NT_STATUS_OK);
250 4 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
251 :
252 4 : torture_comment(tctx, "try open for write\n");
253 4 : io.in.desired_access = SEC_FILE_WRITE_DATA;
254 4 : status = smb2_create(tree, tctx, &io);
255 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
256 :
257 4 : torture_comment(tctx, "try open for read\n");
258 4 : io.in.desired_access = SEC_FILE_READ_DATA;
259 4 : status = smb2_create(tree, tctx, &io);
260 4 : CHECK_STATUS(status, NT_STATUS_OK);
261 8 : CHECK_ACCESS_FLAGS(io.out.file.handle,
262 : SEC_FILE_READ_DATA);
263 4 : smb2_util_close(tree, io.out.file.handle);
264 :
265 4 : torture_comment(tctx, "try open for generic write\n");
266 4 : io.in.desired_access = SEC_GENERIC_WRITE;
267 4 : status = smb2_create(tree, tctx, &io);
268 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
269 :
270 4 : torture_comment(tctx, "try open for generic read\n");
271 4 : io.in.desired_access = SEC_GENERIC_READ;
272 4 : status = smb2_create(tree, tctx, &io);
273 4 : CHECK_STATUS(status, NT_STATUS_OK);
274 4 : CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_RIGHTS_FILE_READ);
275 4 : smb2_util_close(tree, io.out.file.handle);
276 :
277 :
278 4 : torture_comment(tctx, "put back original sd\n");
279 4 : set.set_secdesc.in.sd = sd_orig;
280 4 : status = smb2_setinfo_file(tree, &set);
281 4 : CHECK_STATUS(status, NT_STATUS_OK);
282 :
283 :
284 4 : done:
285 4 : smb2_util_close(tree, handle);
286 4 : smb2_deltree(tree, BASEDIR);
287 4 : smb2_tdis(tree);
288 4 : smb2_logoff(tree->session);
289 4 : return ret;
290 : }
291 :
292 :
293 : /*
294 : test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
295 : SEC_FILE_xx bits
296 : Note: This test was copied from raw/acls.c.
297 : */
298 4 : static bool test_generic_bits(struct torture_context *tctx, struct smb2_tree *tree)
299 : {
300 0 : NTSTATUS status;
301 0 : struct smb2_create io;
302 4 : const char *fname = BASEDIR "\\generic.txt";
303 4 : bool ret = true;
304 4 : struct smb2_handle handle = {{0}};
305 0 : int i;
306 0 : union smb_fileinfo q;
307 0 : union smb_setfileinfo set;
308 0 : struct security_descriptor *sd, *sd_orig, *sd2;
309 0 : const char *owner_sid;
310 0 : const struct {
311 : uint32_t gen_bits;
312 : uint32_t specific_bits;
313 4 : } file_mappings[] = {
314 : { 0, 0 },
315 : { SEC_GENERIC_READ, SEC_RIGHTS_FILE_READ },
316 : { SEC_GENERIC_WRITE, SEC_RIGHTS_FILE_WRITE },
317 : { SEC_GENERIC_EXECUTE, SEC_RIGHTS_FILE_EXECUTE },
318 : { SEC_GENERIC_ALL, SEC_RIGHTS_FILE_ALL },
319 : { SEC_FILE_READ_DATA, SEC_FILE_READ_DATA },
320 : { SEC_FILE_READ_ATTRIBUTE, SEC_FILE_READ_ATTRIBUTE }
321 : };
322 0 : const struct {
323 : uint32_t gen_bits;
324 : uint32_t specific_bits;
325 4 : } dir_mappings[] = {
326 : { 0, 0 },
327 : { SEC_GENERIC_READ, SEC_RIGHTS_DIR_READ },
328 : { SEC_GENERIC_WRITE, SEC_RIGHTS_DIR_WRITE },
329 : { SEC_GENERIC_EXECUTE, SEC_RIGHTS_DIR_EXECUTE },
330 : { SEC_GENERIC_ALL, SEC_RIGHTS_DIR_ALL }
331 : };
332 4 : bool has_restore_privilege = false;
333 4 : bool has_take_ownership_privilege = false;
334 :
335 4 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
336 0 : return false;
337 :
338 4 : torture_comment(tctx, "TESTING FILE GENERIC BITS\n");
339 :
340 4 : ZERO_STRUCT(io);
341 4 : io.level = RAW_OPEN_SMB2;
342 4 : io.in.create_flags = 0;
343 4 : io.in.desired_access =
344 : SEC_STD_READ_CONTROL |
345 : SEC_STD_WRITE_DAC |
346 : SEC_STD_WRITE_OWNER;
347 4 : io.in.create_options = 0;
348 4 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
349 4 : io.in.share_access =
350 : NTCREATEX_SHARE_ACCESS_READ |
351 : NTCREATEX_SHARE_ACCESS_WRITE;
352 4 : io.in.alloc_size = 0;
353 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
354 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
355 4 : io.in.security_flags = 0;
356 4 : io.in.fname = fname;
357 4 : status = smb2_create(tree, tctx, &io);
358 4 : CHECK_STATUS(status, NT_STATUS_OK);
359 4 : handle = io.out.file.handle;
360 :
361 4 : torture_comment(tctx, "get the original sd\n");
362 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
363 4 : q.query_secdesc.in.file.handle = handle;
364 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
365 4 : status = smb2_getinfo_file(tree, tctx, &q);
366 4 : CHECK_STATUS(status, NT_STATUS_OK);
367 4 : sd_orig = q.query_secdesc.out.sd;
368 :
369 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
370 :
371 : /*
372 : * XXX: The smblsa calls use SMB as their transport - need to get rid of
373 : * dependency.
374 : */
375 : /*
376 : status = smblsa_sid_check_privilege(cli,
377 : owner_sid,
378 : sec_privilege_name(SEC_PRIV_RESTORE));
379 : has_restore_privilege = NT_STATUS_IS_OK(status);
380 : if (!NT_STATUS_IS_OK(status)) {
381 : torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
382 : }
383 : torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
384 :
385 : status = smblsa_sid_check_privilege(cli,
386 : owner_sid,
387 : sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
388 : has_take_ownership_privilege = NT_STATUS_IS_OK(status);
389 : if (!NT_STATUS_IS_OK(status)) {
390 : torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
391 : }
392 : torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
393 : */
394 :
395 32 : for (i=0;i<ARRAY_SIZE(file_mappings);i++) {
396 28 : uint32_t expected_mask =
397 : SEC_STD_WRITE_DAC |
398 : SEC_STD_READ_CONTROL |
399 : SEC_FILE_READ_ATTRIBUTE |
400 : SEC_STD_DELETE;
401 28 : uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
402 :
403 28 : if (has_restore_privilege) {
404 0 : expected_mask_anon |= SEC_STD_DELETE;
405 : }
406 :
407 28 : torture_comment(tctx, "Testing generic bits 0x%08x\n",
408 28 : file_mappings[i].gen_bits);
409 28 : sd = security_descriptor_dacl_create(tctx,
410 : 0, owner_sid, NULL,
411 : owner_sid,
412 : SEC_ACE_TYPE_ACCESS_ALLOWED,
413 28 : file_mappings[i].gen_bits,
414 : 0,
415 : NULL);
416 :
417 28 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
418 28 : set.set_secdesc.in.file.handle = handle;
419 28 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
420 28 : set.set_secdesc.in.sd = sd;
421 :
422 28 : status = smb2_setinfo_file(tree, &set);
423 28 : CHECK_STATUS(status, NT_STATUS_OK);
424 :
425 28 : sd2 = security_descriptor_dacl_create(tctx,
426 : 0, owner_sid, NULL,
427 : owner_sid,
428 : SEC_ACE_TYPE_ACCESS_ALLOWED,
429 28 : file_mappings[i].specific_bits,
430 : 0,
431 : NULL);
432 :
433 28 : status = smb2_getinfo_file(tree, tctx, &q);
434 28 : CHECK_STATUS(status, NT_STATUS_OK);
435 28 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
436 :
437 28 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
438 28 : status = smb2_create(tree, tctx, &io);
439 28 : CHECK_STATUS(status, NT_STATUS_OK);
440 28 : CHECK_ACCESS_FLAGS(io.out.file.handle,
441 : expected_mask | file_mappings[i].specific_bits);
442 28 : smb2_util_close(tree, io.out.file.handle);
443 :
444 28 : if (!has_take_ownership_privilege) {
445 28 : continue;
446 : }
447 :
448 0 : torture_comment(tctx, "Testing generic bits 0x%08x (anonymous)\n",
449 0 : file_mappings[i].gen_bits);
450 0 : sd = security_descriptor_dacl_create(tctx,
451 : 0, SID_NT_ANONYMOUS, NULL,
452 : owner_sid,
453 : SEC_ACE_TYPE_ACCESS_ALLOWED,
454 0 : file_mappings[i].gen_bits,
455 : 0,
456 : NULL);
457 :
458 0 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
459 0 : set.set_secdesc.in.file.handle = handle;
460 0 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
461 0 : set.set_secdesc.in.sd = sd;
462 :
463 0 : status = smb2_setinfo_file(tree, &set);
464 0 : CHECK_STATUS(status, NT_STATUS_OK);
465 :
466 0 : sd2 = security_descriptor_dacl_create(tctx,
467 : 0, SID_NT_ANONYMOUS, NULL,
468 : owner_sid,
469 : SEC_ACE_TYPE_ACCESS_ALLOWED,
470 0 : file_mappings[i].specific_bits,
471 : 0,
472 : NULL);
473 :
474 0 : status = smb2_getinfo_file(tree, tctx, &q);
475 0 : CHECK_STATUS(status, NT_STATUS_OK);
476 0 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
477 :
478 0 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
479 0 : status = smb2_create(tree, tctx, &io);
480 0 : CHECK_STATUS(status, NT_STATUS_OK);
481 0 : CHECK_ACCESS_FLAGS(io.out.file.handle,
482 : expected_mask_anon | file_mappings[i].specific_bits);
483 0 : smb2_util_close(tree, io.out.file.handle);
484 : }
485 :
486 4 : torture_comment(tctx, "put back original sd\n");
487 4 : set.set_secdesc.in.sd = sd_orig;
488 4 : status = smb2_setinfo_file(tree, &set);
489 4 : CHECK_STATUS(status, NT_STATUS_OK);
490 :
491 4 : smb2_util_close(tree, handle);
492 4 : smb2_util_unlink(tree, fname);
493 :
494 :
495 4 : torture_comment(tctx, "TESTING DIR GENERIC BITS\n");
496 :
497 4 : ZERO_STRUCT(io);
498 4 : io.level = RAW_OPEN_SMB2;
499 4 : io.in.create_flags = 0;
500 4 : io.in.desired_access =
501 : SEC_STD_READ_CONTROL |
502 : SEC_STD_WRITE_DAC |
503 : SEC_STD_WRITE_OWNER;
504 4 : io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
505 4 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
506 4 : io.in.share_access =
507 : NTCREATEX_SHARE_ACCESS_READ |
508 : NTCREATEX_SHARE_ACCESS_WRITE;
509 4 : io.in.alloc_size = 0;
510 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
511 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
512 4 : io.in.security_flags = 0;
513 4 : io.in.fname = fname;
514 4 : status = smb2_create(tree, tctx, &io);
515 4 : CHECK_STATUS(status, NT_STATUS_OK);
516 4 : handle = io.out.file.handle;
517 :
518 4 : torture_comment(tctx, "get the original sd\n");
519 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
520 4 : q.query_secdesc.in.file.handle = handle;
521 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
522 4 : status = smb2_getinfo_file(tree, tctx, &q);
523 4 : CHECK_STATUS(status, NT_STATUS_OK);
524 4 : sd_orig = q.query_secdesc.out.sd;
525 :
526 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
527 :
528 : /*
529 : * XXX: The smblsa calls use SMB as their transport - need to get rid of
530 : * dependency.
531 : */
532 : /*
533 : status = smblsa_sid_check_privilege(cli,
534 : owner_sid,
535 : sec_privilege_name(SEC_PRIV_RESTORE));
536 : has_restore_privilege = NT_STATUS_IS_OK(status);
537 : if (!NT_STATUS_IS_OK(status)) {
538 : torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
539 : }
540 : torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
541 :
542 : status = smblsa_sid_check_privilege(cli,
543 : owner_sid,
544 : sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
545 : has_take_ownership_privilege = NT_STATUS_IS_OK(status);
546 : if (!NT_STATUS_IS_OK(status)) {
547 : torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
548 : }
549 : torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
550 :
551 : */
552 24 : for (i=0;i<ARRAY_SIZE(dir_mappings);i++) {
553 20 : uint32_t expected_mask =
554 : SEC_STD_WRITE_DAC |
555 : SEC_STD_READ_CONTROL |
556 : SEC_FILE_READ_ATTRIBUTE |
557 : SEC_STD_DELETE;
558 20 : uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
559 :
560 20 : if (has_restore_privilege) {
561 0 : expected_mask_anon |= SEC_STD_DELETE;
562 : }
563 :
564 20 : torture_comment(tctx, "Testing generic bits 0x%08x\n",
565 20 : file_mappings[i].gen_bits);
566 20 : sd = security_descriptor_dacl_create(tctx,
567 : 0, owner_sid, NULL,
568 : owner_sid,
569 : SEC_ACE_TYPE_ACCESS_ALLOWED,
570 20 : dir_mappings[i].gen_bits,
571 : 0,
572 : NULL);
573 :
574 20 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
575 20 : set.set_secdesc.in.file.handle = handle;
576 20 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
577 20 : set.set_secdesc.in.sd = sd;
578 :
579 20 : status = smb2_setinfo_file(tree, &set);
580 20 : CHECK_STATUS(status, NT_STATUS_OK);
581 :
582 20 : sd2 = security_descriptor_dacl_create(tctx,
583 : 0, owner_sid, NULL,
584 : owner_sid,
585 : SEC_ACE_TYPE_ACCESS_ALLOWED,
586 20 : dir_mappings[i].specific_bits,
587 : 0,
588 : NULL);
589 :
590 20 : status = smb2_getinfo_file(tree, tctx, &q);
591 20 : CHECK_STATUS(status, NT_STATUS_OK);
592 20 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
593 :
594 20 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
595 20 : status = smb2_create(tree, tctx, &io);
596 20 : CHECK_STATUS(status, NT_STATUS_OK);
597 20 : CHECK_ACCESS_FLAGS(io.out.file.handle,
598 : expected_mask | dir_mappings[i].specific_bits);
599 20 : smb2_util_close(tree, io.out.file.handle);
600 :
601 20 : if (!has_take_ownership_privilege) {
602 20 : continue;
603 : }
604 :
605 0 : torture_comment(tctx, "Testing generic bits 0x%08x (anonymous)\n",
606 0 : file_mappings[i].gen_bits);
607 0 : sd = security_descriptor_dacl_create(tctx,
608 : 0, SID_NT_ANONYMOUS, NULL,
609 : owner_sid,
610 : SEC_ACE_TYPE_ACCESS_ALLOWED,
611 0 : file_mappings[i].gen_bits,
612 : 0,
613 : NULL);
614 :
615 0 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
616 0 : set.set_secdesc.in.file.handle = handle;
617 0 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
618 0 : set.set_secdesc.in.sd = sd;
619 :
620 0 : status = smb2_setinfo_file(tree, &set);
621 0 : CHECK_STATUS(status, NT_STATUS_OK);
622 :
623 0 : sd2 = security_descriptor_dacl_create(tctx,
624 : 0, SID_NT_ANONYMOUS, NULL,
625 : owner_sid,
626 : SEC_ACE_TYPE_ACCESS_ALLOWED,
627 0 : file_mappings[i].specific_bits,
628 : 0,
629 : NULL);
630 :
631 0 : status = smb2_getinfo_file(tree, tctx, &q);
632 0 : CHECK_STATUS(status, NT_STATUS_OK);
633 0 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
634 :
635 0 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
636 0 : status = smb2_create(tree, tctx, &io);
637 0 : CHECK_STATUS(status, NT_STATUS_OK);
638 0 : CHECK_ACCESS_FLAGS(io.out.file.handle,
639 : expected_mask_anon | dir_mappings[i].specific_bits);
640 0 : smb2_util_close(tree, io.out.file.handle);
641 : }
642 :
643 4 : torture_comment(tctx, "put back original sd\n");
644 4 : set.set_secdesc.in.sd = sd_orig;
645 4 : status = smb2_setinfo_file(tree, &set);
646 4 : CHECK_STATUS(status, NT_STATUS_OK);
647 :
648 4 : smb2_util_close(tree, handle);
649 4 : smb2_util_unlink(tree, fname);
650 :
651 4 : done:
652 4 : smb2_util_close(tree, handle);
653 4 : smb2_deltree(tree, BASEDIR);
654 4 : smb2_tdis(tree);
655 4 : smb2_logoff(tree->session);
656 4 : return ret;
657 : }
658 :
659 :
660 : /*
661 : see what access bits the owner of a file always gets
662 : Note: This test was copied from raw/acls.c.
663 : */
664 4 : static bool test_owner_bits(struct torture_context *tctx, struct smb2_tree *tree)
665 : {
666 0 : NTSTATUS status;
667 0 : struct smb2_create io;
668 4 : const char *fname = BASEDIR "\\test_owner_bits.txt";
669 4 : bool ret = true;
670 4 : struct smb2_handle handle = {{0}};
671 0 : int i;
672 0 : union smb_fileinfo q;
673 0 : union smb_setfileinfo set;
674 0 : struct security_descriptor *sd, *sd_orig;
675 0 : const char *owner_sid;
676 0 : uint32_t expected_bits;
677 :
678 4 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
679 0 : return false;
680 :
681 4 : torture_comment(tctx, "TESTING FILE OWNER BITS\n");
682 :
683 4 : ZERO_STRUCT(io);
684 4 : io.level = RAW_OPEN_SMB2;
685 4 : io.in.create_flags = 0;
686 4 : io.in.desired_access =
687 : SEC_STD_READ_CONTROL |
688 : SEC_STD_WRITE_DAC |
689 : SEC_STD_WRITE_OWNER;
690 4 : io.in.create_options = 0;
691 4 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
692 4 : io.in.share_access =
693 : NTCREATEX_SHARE_ACCESS_READ |
694 : NTCREATEX_SHARE_ACCESS_WRITE;
695 4 : io.in.alloc_size = 0;
696 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
697 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
698 4 : io.in.security_flags = 0;
699 4 : io.in.fname = fname;
700 4 : status = smb2_create(tree, tctx, &io);
701 4 : CHECK_STATUS(status, NT_STATUS_OK);
702 4 : handle = io.out.file.handle;
703 :
704 4 : torture_comment(tctx, "get the original sd\n");
705 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
706 4 : q.query_secdesc.in.file.handle = handle;
707 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
708 4 : status = smb2_getinfo_file(tree, tctx, &q);
709 4 : CHECK_STATUS(status, NT_STATUS_OK);
710 4 : sd_orig = q.query_secdesc.out.sd;
711 :
712 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
713 :
714 : /*
715 : * XXX: The smblsa calls use SMB as their transport - need to get rid of
716 : * dependency.
717 : */
718 : /*
719 : status = smblsa_sid_check_privilege(cli,
720 : owner_sid,
721 : sec_privilege_name(SEC_PRIV_RESTORE));
722 : has_restore_privilege = NT_STATUS_IS_OK(status);
723 : if (!NT_STATUS_IS_OK(status)) {
724 : torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
725 : }
726 : torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
727 :
728 : status = smblsa_sid_check_privilege(cli,
729 : owner_sid,
730 : sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
731 : has_take_ownership_privilege = NT_STATUS_IS_OK(status);
732 : if (!NT_STATUS_IS_OK(status)) {
733 : torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
734 : }
735 : torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
736 : */
737 :
738 4 : sd = security_descriptor_dacl_create(tctx,
739 : 0, NULL, NULL,
740 : owner_sid,
741 : SEC_ACE_TYPE_ACCESS_ALLOWED,
742 : SEC_FILE_WRITE_DATA,
743 : 0,
744 : NULL);
745 :
746 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
747 4 : set.set_secdesc.in.file.handle = handle;
748 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
749 4 : set.set_secdesc.in.sd = sd;
750 :
751 4 : status = smb2_setinfo_file(tree, &set);
752 4 : CHECK_STATUS(status, NT_STATUS_OK);
753 :
754 4 : expected_bits = SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE;
755 :
756 68 : for (i=0;i<16;i++) {
757 64 : uint32_t bit = (1<<i);
758 64 : io.in.desired_access = bit;
759 64 : status = smb2_create(tree, tctx, &io);
760 64 : if (expected_bits & bit) {
761 8 : if (!NT_STATUS_IS_OK(status)) {
762 0 : torture_warning(tctx, "failed with access mask 0x%08x of expected 0x%08x\n",
763 : bit, expected_bits);
764 : }
765 8 : CHECK_STATUS(status, NT_STATUS_OK);
766 8 : CHECK_ACCESS_FLAGS(io.out.file.handle, bit);
767 8 : smb2_util_close(tree, io.out.file.handle);
768 : } else {
769 56 : if (NT_STATUS_IS_OK(status)) {
770 0 : torture_warning(tctx, "open succeeded with access mask 0x%08x of "
771 : "expected 0x%08x - should fail\n",
772 : bit, expected_bits);
773 : }
774 56 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
775 : }
776 : }
777 :
778 4 : torture_comment(tctx, "put back original sd\n");
779 4 : set.set_secdesc.in.sd = sd_orig;
780 4 : status = smb2_setinfo_file(tree, &set);
781 4 : CHECK_STATUS(status, NT_STATUS_OK);
782 :
783 4 : done:
784 4 : smb2_util_close(tree, handle);
785 4 : smb2_util_unlink(tree, fname);
786 4 : smb2_deltree(tree, BASEDIR);
787 4 : smb2_tdis(tree);
788 4 : smb2_logoff(tree->session);
789 4 : return ret;
790 : }
791 :
792 :
793 :
794 : /*
795 : test the inheritance of ACL flags onto new files and directories
796 : Note: This test was copied from raw/acls.c.
797 : */
798 4 : static bool test_inheritance(struct torture_context *tctx, struct smb2_tree *tree)
799 : {
800 0 : NTSTATUS status;
801 0 : struct smb2_create io;
802 4 : const char *dname = BASEDIR "\\inheritance";
803 4 : const char *fname1 = BASEDIR "\\inheritance\\testfile";
804 4 : const char *fname2 = BASEDIR "\\inheritance\\testdir";
805 4 : bool ret = true;
806 4 : struct smb2_handle handle = {{0}};
807 4 : struct smb2_handle handle2 = {{0}};
808 0 : int i;
809 0 : union smb_fileinfo q;
810 0 : union smb_setfileinfo set;
811 4 : struct security_descriptor *sd, *sd2, *sd_orig=NULL, *sd_def1, *sd_def2;
812 0 : const char *owner_sid;
813 0 : const struct dom_sid *creator_owner;
814 0 : const struct {
815 : uint32_t parent_flags;
816 : uint32_t file_flags;
817 : uint32_t dir_flags;
818 4 : } test_flags[] = {
819 : {
820 : 0,
821 : 0,
822 : 0
823 : },
824 : {
825 : SEC_ACE_FLAG_OBJECT_INHERIT,
826 : 0,
827 : SEC_ACE_FLAG_OBJECT_INHERIT |
828 : SEC_ACE_FLAG_INHERIT_ONLY,
829 : },
830 : {
831 : SEC_ACE_FLAG_CONTAINER_INHERIT,
832 : 0,
833 : SEC_ACE_FLAG_CONTAINER_INHERIT,
834 : },
835 : {
836 : SEC_ACE_FLAG_OBJECT_INHERIT |
837 : SEC_ACE_FLAG_CONTAINER_INHERIT,
838 : 0,
839 : SEC_ACE_FLAG_OBJECT_INHERIT |
840 : SEC_ACE_FLAG_CONTAINER_INHERIT,
841 : },
842 : {
843 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
844 : 0,
845 : 0,
846 : },
847 : {
848 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
849 : SEC_ACE_FLAG_OBJECT_INHERIT,
850 : 0,
851 : 0,
852 : },
853 : {
854 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
855 : SEC_ACE_FLAG_CONTAINER_INHERIT,
856 : 0,
857 : 0,
858 : },
859 : {
860 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
861 : SEC_ACE_FLAG_CONTAINER_INHERIT |
862 : SEC_ACE_FLAG_OBJECT_INHERIT,
863 : 0,
864 : 0,
865 : },
866 : {
867 : SEC_ACE_FLAG_INHERIT_ONLY,
868 : 0,
869 : 0,
870 : },
871 : {
872 : SEC_ACE_FLAG_INHERIT_ONLY |
873 : SEC_ACE_FLAG_OBJECT_INHERIT,
874 : 0,
875 : SEC_ACE_FLAG_OBJECT_INHERIT |
876 : SEC_ACE_FLAG_INHERIT_ONLY,
877 : },
878 : {
879 : SEC_ACE_FLAG_INHERIT_ONLY |
880 : SEC_ACE_FLAG_CONTAINER_INHERIT,
881 : 0,
882 : SEC_ACE_FLAG_CONTAINER_INHERIT,
883 : },
884 : {
885 : SEC_ACE_FLAG_INHERIT_ONLY |
886 : SEC_ACE_FLAG_CONTAINER_INHERIT |
887 : SEC_ACE_FLAG_OBJECT_INHERIT,
888 : 0,
889 : SEC_ACE_FLAG_CONTAINER_INHERIT |
890 : SEC_ACE_FLAG_OBJECT_INHERIT,
891 : },
892 : {
893 : SEC_ACE_FLAG_INHERIT_ONLY |
894 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
895 : 0,
896 : 0,
897 : },
898 : {
899 : SEC_ACE_FLAG_INHERIT_ONLY |
900 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
901 : SEC_ACE_FLAG_OBJECT_INHERIT,
902 : 0,
903 : 0,
904 : },
905 : {
906 : SEC_ACE_FLAG_INHERIT_ONLY |
907 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
908 : SEC_ACE_FLAG_CONTAINER_INHERIT,
909 : 0,
910 : 0,
911 : },
912 : {
913 : SEC_ACE_FLAG_INHERIT_ONLY |
914 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
915 : SEC_ACE_FLAG_CONTAINER_INHERIT |
916 : SEC_ACE_FLAG_OBJECT_INHERIT,
917 : 0,
918 : 0,
919 : }
920 : };
921 :
922 4 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
923 0 : return false;
924 :
925 4 : torture_comment(tctx, "TESTING ACL INHERITANCE\n");
926 :
927 4 : ZERO_STRUCT(io);
928 4 : io.level = RAW_OPEN_SMB2;
929 4 : io.in.create_flags = 0;
930 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
931 4 : io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
932 4 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
933 4 : io.in.share_access = 0;
934 4 : io.in.alloc_size = 0;
935 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
936 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
937 4 : io.in.security_flags = 0;
938 4 : io.in.fname = dname;
939 :
940 4 : status = smb2_create(tree, tctx, &io);
941 4 : CHECK_STATUS(status, NT_STATUS_OK);
942 4 : handle = io.out.file.handle;
943 :
944 4 : torture_comment(tctx, "get the original sd\n");
945 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
946 4 : q.query_secdesc.in.file.handle = handle;
947 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
948 4 : status = smb2_getinfo_file(tree, tctx, &q);
949 4 : CHECK_STATUS(status, NT_STATUS_OK);
950 4 : sd_orig = q.query_secdesc.out.sd;
951 :
952 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
953 :
954 4 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
955 :
956 : /*
957 : * The Windows Default ACL for a new file, when there is no ACL to be
958 : * inherited: FullControl for the owner and SYSTEM.
959 : */
960 4 : sd_def1 = security_descriptor_dacl_create(tctx,
961 : 0, owner_sid, NULL,
962 : owner_sid,
963 : SEC_ACE_TYPE_ACCESS_ALLOWED,
964 : SEC_RIGHTS_FILE_ALL,
965 : 0,
966 : SID_NT_SYSTEM,
967 : SEC_ACE_TYPE_ACCESS_ALLOWED,
968 : SEC_RIGHTS_FILE_ALL,
969 : 0,
970 : NULL);
971 :
972 : /*
973 : * Use this in the case the system being tested does not add an ACE for
974 : * the SYSTEM SID.
975 : */
976 4 : sd_def2 = security_descriptor_dacl_create(tctx,
977 : 0, owner_sid, NULL,
978 : owner_sid,
979 : SEC_ACE_TYPE_ACCESS_ALLOWED,
980 : SEC_RIGHTS_FILE_ALL,
981 : 0,
982 : NULL);
983 :
984 4 : creator_owner = dom_sid_parse_talloc(tctx, SID_CREATOR_OWNER);
985 :
986 68 : for (i=0;i<ARRAY_SIZE(test_flags);i++) {
987 64 : sd = security_descriptor_dacl_create(tctx,
988 : 0, NULL, NULL,
989 : SID_CREATOR_OWNER,
990 : SEC_ACE_TYPE_ACCESS_ALLOWED,
991 : SEC_FILE_WRITE_DATA,
992 64 : test_flags[i].parent_flags,
993 : SID_WORLD,
994 : SEC_ACE_TYPE_ACCESS_ALLOWED,
995 : SEC_FILE_ALL | SEC_STD_ALL,
996 : 0,
997 : NULL);
998 64 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
999 64 : set.set_secdesc.in.file.handle = handle;
1000 64 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1001 64 : set.set_secdesc.in.sd = sd;
1002 64 : status = smb2_setinfo_file(tree, &set);
1003 64 : CHECK_STATUS(status, NT_STATUS_OK);
1004 :
1005 64 : io.in.fname = fname1;
1006 64 : io.in.create_options = 0;
1007 64 : status = smb2_create(tree, tctx, &io);
1008 64 : CHECK_STATUS(status, NT_STATUS_OK);
1009 64 : handle2 = io.out.file.handle;
1010 :
1011 64 : q.query_secdesc.in.file.handle = handle2;
1012 64 : status = smb2_getinfo_file(tree, tctx, &q);
1013 64 : CHECK_STATUS(status, NT_STATUS_OK);
1014 :
1015 64 : smb2_util_close(tree, handle2);
1016 64 : smb2_util_unlink(tree, fname1);
1017 :
1018 64 : if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
1019 32 : if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def1) &&
1020 32 : !security_descriptor_equal(q.query_secdesc.out.sd, sd_def2)) {
1021 32 : torture_warning(tctx, "Expected default sd:\n");
1022 32 : NDR_PRINT_DEBUG(security_descriptor, sd_def1);
1023 32 : torture_warning(tctx, "at %d - got:\n", i);
1024 32 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1025 : }
1026 32 : goto check_dir;
1027 : }
1028 :
1029 32 : if (q.query_secdesc.out.sd->dacl == NULL ||
1030 32 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1031 32 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1032 32 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1033 32 : sd_orig->owner_sid)) {
1034 0 : torture_warning(tctx, "Bad sd in child file at %d\n", i);
1035 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1036 0 : ret = false;
1037 0 : goto check_dir;
1038 : }
1039 :
1040 32 : if (q.query_secdesc.out.sd->dacl->aces[0].flags !=
1041 32 : test_flags[i].file_flags) {
1042 0 : torture_warning(tctx, "incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1043 0 : q.query_secdesc.out.sd->dacl->aces[0].flags,
1044 0 : test_flags[i].file_flags,
1045 0 : test_flags[i].parent_flags,
1046 : i);
1047 0 : ret = false;
1048 : }
1049 :
1050 32 : check_dir:
1051 64 : io.in.fname = fname2;
1052 64 : io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1053 64 : status = smb2_create(tree, tctx, &io);
1054 64 : CHECK_STATUS(status, NT_STATUS_OK);
1055 64 : handle2 = io.out.file.handle;
1056 :
1057 64 : q.query_secdesc.in.file.handle = handle2;
1058 64 : status = smb2_getinfo_file(tree, tctx, &q);
1059 64 : CHECK_STATUS(status, NT_STATUS_OK);
1060 :
1061 64 : smb2_util_close(tree, handle2);
1062 64 : smb2_util_rmdir(tree, fname2);
1063 :
1064 64 : if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1065 32 : (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT) ||
1066 16 : (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT))) {
1067 24 : if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def1) &&
1068 24 : !security_descriptor_equal(q.query_secdesc.out.sd, sd_def2)) {
1069 24 : torture_warning(tctx, "Expected default sd for dir at %d:\n", i);
1070 24 : NDR_PRINT_DEBUG(security_descriptor, sd_def1);
1071 24 : torture_warning(tctx, "got:\n");
1072 24 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1073 : }
1074 24 : continue;
1075 : }
1076 :
1077 40 : if ((test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1078 32 : (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
1079 16 : if (q.query_secdesc.out.sd->dacl == NULL ||
1080 16 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1081 16 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1082 16 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1083 16 : sd_orig->owner_sid) ||
1084 16 : q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1085 0 : torture_warning(tctx, "(CI & NP) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1086 0 : test_flags[i].dir_flags,
1087 0 : test_flags[i].parent_flags, i);
1088 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1089 0 : torture_warning(tctx, "FYI, here is the parent sd:\n");
1090 0 : NDR_PRINT_DEBUG(security_descriptor, sd);
1091 0 : ret = false;
1092 0 : continue;
1093 : }
1094 24 : } else if (test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
1095 16 : if (q.query_secdesc.out.sd->dacl == NULL ||
1096 16 : q.query_secdesc.out.sd->dacl->num_aces != 2 ||
1097 16 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1098 16 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1099 16 : sd_orig->owner_sid) ||
1100 16 : q.query_secdesc.out.sd->dacl->aces[1].access_mask != SEC_FILE_WRITE_DATA ||
1101 16 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[1].trustee,
1102 16 : creator_owner) ||
1103 16 : q.query_secdesc.out.sd->dacl->aces[0].flags != 0 ||
1104 16 : q.query_secdesc.out.sd->dacl->aces[1].flags !=
1105 16 : (test_flags[i].dir_flags | SEC_ACE_FLAG_INHERIT_ONLY)) {
1106 0 : torture_warning(tctx, "(CI) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1107 0 : test_flags[i].dir_flags,
1108 0 : test_flags[i].parent_flags, i);
1109 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1110 0 : torture_warning(tctx, "FYI, here is the parent sd:\n");
1111 0 : NDR_PRINT_DEBUG(security_descriptor, sd);
1112 0 : ret = false;
1113 0 : continue;
1114 : }
1115 : } else {
1116 8 : if (q.query_secdesc.out.sd->dacl == NULL ||
1117 8 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1118 8 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1119 8 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1120 8 : creator_owner) ||
1121 8 : q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1122 0 : torture_warning(tctx, "(0) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1123 0 : test_flags[i].dir_flags,
1124 0 : test_flags[i].parent_flags, i);
1125 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1126 0 : torture_warning(tctx, "FYI, here is the parent sd:\n");
1127 0 : NDR_PRINT_DEBUG(security_descriptor, sd);
1128 0 : ret = false;
1129 0 : continue;
1130 : }
1131 : }
1132 : }
1133 :
1134 4 : torture_comment(tctx, "Testing access checks on inherited create with %s\n", fname1);
1135 4 : sd = security_descriptor_dacl_create(tctx,
1136 : 0, NULL, NULL,
1137 : owner_sid,
1138 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1139 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1140 : SEC_ACE_FLAG_OBJECT_INHERIT,
1141 : SID_WORLD,
1142 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1143 : SEC_FILE_ALL | SEC_STD_ALL,
1144 : 0,
1145 : NULL);
1146 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1147 4 : set.set_secdesc.in.file.handle = handle;
1148 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1149 4 : set.set_secdesc.in.sd = sd;
1150 4 : status = smb2_setinfo_file(tree, &set);
1151 4 : CHECK_STATUS(status, NT_STATUS_OK);
1152 :
1153 : /* Check DACL we just set. */
1154 4 : torture_comment(tctx, "checking new sd\n");
1155 4 : q.query_secdesc.in.file.handle = handle;
1156 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
1157 4 : status = smb2_getinfo_file(tree, tctx, &q);
1158 4 : CHECK_STATUS(status, NT_STATUS_OK);
1159 4 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
1160 :
1161 4 : io.in.fname = fname1;
1162 4 : io.in.create_options = 0;
1163 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1164 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1165 4 : status = smb2_create(tree, tctx, &io);
1166 4 : CHECK_STATUS(status, NT_STATUS_OK);
1167 4 : handle2 = io.out.file.handle;
1168 4 : CHECK_ACCESS_FLAGS(handle2, SEC_RIGHTS_FILE_ALL);
1169 :
1170 4 : q.query_secdesc.in.file.handle = handle2;
1171 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1172 4 : status = smb2_getinfo_file(tree, tctx, &q);
1173 4 : CHECK_STATUS(status, NT_STATUS_OK);
1174 4 : smb2_util_close(tree, handle2);
1175 :
1176 4 : sd2 = security_descriptor_dacl_create(tctx,
1177 : 0, owner_sid, NULL,
1178 : owner_sid,
1179 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1180 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1181 : 0,
1182 : NULL);
1183 4 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1184 :
1185 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1186 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1187 4 : status = smb2_create(tree, tctx, &io);
1188 4 : if (NT_STATUS_IS_OK(status)) {
1189 0 : torture_warning(tctx, "failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1190 0 : ret = false;
1191 0 : handle2 = io.out.file.handle;
1192 0 : CHECK_ACCESS_FLAGS(handle2, SEC_RIGHTS_FILE_ALL);
1193 0 : smb2_util_close(tree, handle2);
1194 : } else {
1195 4 : if (torture_setting_bool(tctx, "hide_on_access_denied",
1196 : false)) {
1197 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1198 : } else {
1199 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1200 : }
1201 : }
1202 :
1203 4 : torture_comment(tctx, "trying without execute\n");
1204 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1205 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL & ~SEC_FILE_EXECUTE;
1206 4 : status = smb2_create(tree, tctx, &io);
1207 4 : if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1208 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1209 : } else {
1210 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1211 : }
1212 :
1213 4 : torture_comment(tctx, "and with full permissions again\n");
1214 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1215 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1216 4 : status = smb2_create(tree, tctx, &io);
1217 4 : if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1218 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1219 : } else {
1220 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1221 : }
1222 :
1223 4 : io.in.desired_access = SEC_FILE_WRITE_DATA;
1224 4 : status = smb2_create(tree, tctx, &io);
1225 4 : CHECK_STATUS(status, NT_STATUS_OK);
1226 4 : handle2 = io.out.file.handle;
1227 8 : CHECK_ACCESS_FLAGS(handle2, SEC_FILE_WRITE_DATA);
1228 4 : smb2_util_close(tree, handle2);
1229 :
1230 4 : torture_comment(tctx, "put back original sd\n");
1231 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1232 4 : set.set_secdesc.in.file.handle = handle;
1233 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1234 4 : set.set_secdesc.in.sd = sd_orig;
1235 4 : status = smb2_setinfo_file(tree, &set);
1236 4 : CHECK_STATUS(status, NT_STATUS_OK);
1237 :
1238 4 : smb2_util_close(tree, handle);
1239 :
1240 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1241 4 : status = smb2_create(tree, tctx, &io);
1242 4 : if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1243 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1244 : } else {
1245 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1246 : }
1247 :
1248 4 : io.in.desired_access = SEC_FILE_WRITE_DATA;
1249 4 : status = smb2_create(tree, tctx, &io);
1250 4 : CHECK_STATUS(status, NT_STATUS_OK);
1251 4 : handle2 = io.out.file.handle;
1252 8 : CHECK_ACCESS_FLAGS(handle2, SEC_FILE_WRITE_DATA);
1253 4 : smb2_util_close(tree, handle2);
1254 :
1255 4 : smb2_util_unlink(tree, fname1);
1256 4 : smb2_util_rmdir(tree, dname);
1257 :
1258 4 : done:
1259 4 : if (sd_orig != NULL) {
1260 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1261 4 : set.set_secdesc.in.file.handle = handle;
1262 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1263 4 : set.set_secdesc.in.sd = sd_orig;
1264 4 : status = smb2_setinfo_file(tree, &set);
1265 : }
1266 :
1267 4 : smb2_util_close(tree, handle);
1268 4 : smb2_deltree(tree, BASEDIR);
1269 4 : smb2_tdis(tree);
1270 4 : smb2_logoff(tree->session);
1271 4 : return ret;
1272 : }
1273 :
1274 4 : static bool test_inheritance_flags(struct torture_context *tctx,
1275 : struct smb2_tree *tree)
1276 : {
1277 0 : NTSTATUS status;
1278 0 : struct smb2_create io;
1279 4 : const char *dname = BASEDIR "\\inheritance";
1280 4 : const char *fname1 = BASEDIR "\\inheritance\\testfile";
1281 4 : bool ret = true;
1282 4 : struct smb2_handle handle = {{0}};
1283 4 : struct smb2_handle handle2 = {{0}};
1284 0 : int i, j;
1285 0 : union smb_fileinfo q;
1286 0 : union smb_setfileinfo set;
1287 4 : struct security_descriptor *sd, *sd2, *sd_orig=NULL;
1288 0 : const char *owner_sid;
1289 0 : struct {
1290 : uint32_t parent_set_sd_type; /* 3 options */
1291 : uint32_t parent_set_ace_inherit; /* 1 option */
1292 : uint32_t parent_get_sd_type;
1293 : uint32_t parent_get_ace_inherit;
1294 : uint32_t child_get_sd_type;
1295 : uint32_t child_get_ace_inherit;
1296 4 : } tflags[16] = {{0}}; /* 2^4 */
1297 :
1298 64 : for (i = 0; i < 15; i++) {
1299 60 : torture_comment(tctx, "i=%d:", i);
1300 :
1301 60 : if (i & 1) {
1302 28 : tflags[i].parent_set_sd_type |=
1303 : SEC_DESC_DACL_AUTO_INHERITED;
1304 28 : torture_comment(tctx, "AUTO_INHERITED, ");
1305 : }
1306 60 : if (i & 2) {
1307 28 : tflags[i].parent_set_sd_type |=
1308 : SEC_DESC_DACL_AUTO_INHERIT_REQ;
1309 28 : torture_comment(tctx, "AUTO_INHERIT_REQ, ");
1310 : }
1311 60 : if (i & 4) {
1312 28 : tflags[i].parent_set_sd_type |=
1313 : SEC_DESC_DACL_PROTECTED;
1314 28 : torture_comment(tctx, "PROTECTED, ");
1315 28 : tflags[i].parent_get_sd_type |=
1316 : SEC_DESC_DACL_PROTECTED;
1317 : }
1318 60 : if (i & 8) {
1319 28 : tflags[i].parent_set_ace_inherit |=
1320 : SEC_ACE_FLAG_INHERITED_ACE;
1321 28 : torture_comment(tctx, "INHERITED, ");
1322 28 : tflags[i].parent_get_ace_inherit |=
1323 : SEC_ACE_FLAG_INHERITED_ACE;
1324 : }
1325 :
1326 60 : if ((tflags[i].parent_set_sd_type &
1327 : (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) ==
1328 : (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) {
1329 12 : tflags[i].parent_get_sd_type |=
1330 : SEC_DESC_DACL_AUTO_INHERITED;
1331 12 : tflags[i].child_get_sd_type |=
1332 : SEC_DESC_DACL_AUTO_INHERITED;
1333 12 : tflags[i].child_get_ace_inherit |=
1334 : SEC_ACE_FLAG_INHERITED_ACE;
1335 12 : torture_comment(tctx, " ... parent is AUTO INHERITED");
1336 : }
1337 :
1338 60 : if (tflags[i].parent_set_ace_inherit &
1339 : SEC_ACE_FLAG_INHERITED_ACE) {
1340 28 : tflags[i].parent_get_ace_inherit =
1341 : SEC_ACE_FLAG_INHERITED_ACE;
1342 28 : torture_comment(tctx, " ... parent ACE is INHERITED");
1343 : }
1344 :
1345 60 : torture_comment(tctx, "\n");
1346 : }
1347 :
1348 4 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
1349 0 : return false;
1350 :
1351 4 : torture_comment(tctx, "TESTING ACL INHERITANCE FLAGS\n");
1352 :
1353 4 : ZERO_STRUCT(io);
1354 4 : io.level = RAW_OPEN_SMB2;
1355 4 : io.in.create_flags = 0;
1356 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1357 4 : io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1358 4 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1359 4 : io.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
1360 4 : io.in.alloc_size = 0;
1361 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1362 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
1363 4 : io.in.security_flags = 0;
1364 4 : io.in.fname = dname;
1365 :
1366 4 : torture_comment(tctx, "creating initial directory %s\n", dname);
1367 4 : status = smb2_create(tree, tctx, &io);
1368 4 : CHECK_STATUS(status, NT_STATUS_OK);
1369 4 : handle = io.out.file.handle;
1370 :
1371 4 : torture_comment(tctx, "getting original sd\n");
1372 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1373 4 : q.query_secdesc.in.file.handle = handle;
1374 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1375 4 : status = smb2_getinfo_file(tree, tctx, &q);
1376 4 : CHECK_STATUS(status, NT_STATUS_OK);
1377 4 : sd_orig = q.query_secdesc.out.sd;
1378 :
1379 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1380 4 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
1381 :
1382 68 : for (i=0; i < ARRAY_SIZE(tflags); i++) {
1383 64 : torture_comment(tctx, "setting a new sd on directory, pass #%d\n", i);
1384 :
1385 64 : sd = security_descriptor_dacl_create(tctx,
1386 64 : tflags[i].parent_set_sd_type,
1387 : NULL, NULL,
1388 : owner_sid,
1389 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1390 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1391 : SEC_ACE_FLAG_OBJECT_INHERIT |
1392 : SEC_ACE_FLAG_CONTAINER_INHERIT |
1393 64 : tflags[i].parent_set_ace_inherit,
1394 : SID_WORLD,
1395 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1396 : SEC_FILE_ALL | SEC_STD_ALL,
1397 : 0,
1398 : NULL);
1399 64 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1400 64 : set.set_secdesc.in.file.handle = handle;
1401 64 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1402 64 : set.set_secdesc.in.sd = sd;
1403 64 : status = smb2_setinfo_file(tree, &set);
1404 64 : CHECK_STATUS(status, NT_STATUS_OK);
1405 :
1406 : /*
1407 : * Check DACL we just set, except change the bits to what they
1408 : * should be.
1409 : */
1410 64 : torture_comment(tctx, " checking new sd\n");
1411 :
1412 : /* REQ bit should always be false. */
1413 64 : sd->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
1414 :
1415 64 : if ((tflags[i].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
1416 52 : sd->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
1417 :
1418 64 : q.query_secdesc.in.file.handle = handle;
1419 64 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
1420 64 : status = smb2_getinfo_file(tree, tctx, &q);
1421 64 : CHECK_STATUS(status, NT_STATUS_OK);
1422 64 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
1423 :
1424 : /* Create file. */
1425 64 : torture_comment(tctx, " creating file %s\n", fname1);
1426 64 : io.in.fname = fname1;
1427 64 : io.in.create_options = 0;
1428 64 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1429 64 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1430 64 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1431 64 : status = smb2_create(tree, tctx, &io);
1432 64 : CHECK_STATUS(status, NT_STATUS_OK);
1433 64 : handle2 = io.out.file.handle;
1434 64 : CHECK_ACCESS_FLAGS(handle2, SEC_RIGHTS_FILE_ALL);
1435 :
1436 64 : q.query_secdesc.in.file.handle = handle2;
1437 64 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1438 64 : status = smb2_getinfo_file(tree, tctx, &q);
1439 64 : CHECK_STATUS(status, NT_STATUS_OK);
1440 :
1441 64 : torture_comment(tctx, " checking sd on file %s\n", fname1);
1442 64 : sd2 = security_descriptor_dacl_create(tctx,
1443 64 : tflags[i].child_get_sd_type,
1444 : owner_sid, NULL,
1445 : owner_sid,
1446 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1447 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1448 : tflags[i].child_get_ace_inherit,
1449 : NULL);
1450 64 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1451 :
1452 : /*
1453 : * Set new sd on file ... prove that the bits have nothing to
1454 : * do with the parents bits when manually setting an ACL. The
1455 : * _AUTO_INHERITED bit comes directly from the ACL set.
1456 : */
1457 1088 : for (j = 0; j < ARRAY_SIZE(tflags); j++) {
1458 1024 : torture_comment(tctx, " setting new file sd, pass #%d\n", j);
1459 :
1460 : /* Change sd type. */
1461 1024 : sd2->type &= ~(SEC_DESC_DACL_AUTO_INHERITED |
1462 : SEC_DESC_DACL_AUTO_INHERIT_REQ |
1463 : SEC_DESC_DACL_PROTECTED);
1464 1024 : sd2->type |= tflags[j].parent_set_sd_type;
1465 :
1466 1024 : sd2->dacl->aces[0].flags &=
1467 : ~SEC_ACE_FLAG_INHERITED_ACE;
1468 1024 : sd2->dacl->aces[0].flags |=
1469 1024 : tflags[j].parent_set_ace_inherit;
1470 :
1471 1024 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1472 1024 : set.set_secdesc.in.file.handle = handle2;
1473 1024 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1474 1024 : set.set_secdesc.in.sd = sd2;
1475 1024 : status = smb2_setinfo_file(tree, &set);
1476 1024 : CHECK_STATUS(status, NT_STATUS_OK);
1477 :
1478 : /* Check DACL we just set. */
1479 1024 : sd2->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
1480 1024 : if ((tflags[j].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
1481 832 : sd2->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
1482 :
1483 1024 : q.query_secdesc.in.file.handle = handle2;
1484 1024 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1485 1024 : status = smb2_getinfo_file(tree, tctx, &q);
1486 1024 : CHECK_STATUS(status, NT_STATUS_OK);
1487 :
1488 1024 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1489 : }
1490 :
1491 64 : smb2_util_close(tree, handle2);
1492 64 : smb2_util_unlink(tree, fname1);
1493 : }
1494 :
1495 4 : done:
1496 4 : smb2_util_close(tree, handle);
1497 4 : smb2_deltree(tree, BASEDIR);
1498 4 : smb2_tdis(tree);
1499 4 : smb2_logoff(tree->session);
1500 4 : return ret;
1501 : }
1502 :
1503 : /*
1504 : * This is basically a copy of test_inheritance_flags() with an additional twist
1505 : * to change the owner of the testfile, verifying that the security descriptor
1506 : * flags are not altered.
1507 : */
1508 4 : static bool test_sd_flags_vs_chown(struct torture_context *tctx,
1509 : struct smb2_tree *tree)
1510 : {
1511 0 : NTSTATUS status;
1512 0 : struct smb2_create io;
1513 4 : const char *dname = BASEDIR "\\inheritance";
1514 4 : const char *fname1 = BASEDIR "\\inheritance\\testfile";
1515 4 : bool ret = true;
1516 4 : struct smb2_handle handle = {{0}};
1517 4 : struct smb2_handle handle2 = {{0}};
1518 0 : int i, j;
1519 0 : union smb_fileinfo q;
1520 0 : union smb_setfileinfo set;
1521 4 : struct security_descriptor *sd, *sd2, *sd_orig=NULL;
1522 4 : struct security_descriptor *owner_sd = NULL;
1523 4 : const char *owner_sid_string = NULL;
1524 4 : struct dom_sid *owner_sid = NULL;
1525 4 : struct dom_sid world_sid = global_sid_World;
1526 0 : struct {
1527 : uint32_t parent_set_sd_type; /* 3 options */
1528 : uint32_t parent_set_ace_inherit; /* 1 option */
1529 : uint32_t parent_get_sd_type;
1530 : uint32_t parent_get_ace_inherit;
1531 : uint32_t child_get_sd_type;
1532 : uint32_t child_get_ace_inherit;
1533 4 : } tflags[16] = {{0}}; /* 2^4 */
1534 :
1535 4 : owner_sd = security_descriptor_dacl_create(tctx,
1536 : 0,
1537 : SID_WORLD,
1538 : NULL,
1539 : NULL);
1540 4 : torture_assert_not_null_goto(tctx, owner_sd, ret, done,
1541 : "security_descriptor_dacl_create failed\n");
1542 :
1543 64 : for (i = 0; i < 15; i++) {
1544 60 : torture_comment(tctx, "i=%d:", i);
1545 :
1546 60 : if (i & 1) {
1547 28 : tflags[i].parent_set_sd_type |=
1548 : SEC_DESC_DACL_AUTO_INHERITED;
1549 28 : torture_comment(tctx, "AUTO_INHERITED, ");
1550 : }
1551 60 : if (i & 2) {
1552 28 : tflags[i].parent_set_sd_type |=
1553 : SEC_DESC_DACL_AUTO_INHERIT_REQ;
1554 28 : torture_comment(tctx, "AUTO_INHERIT_REQ, ");
1555 : }
1556 60 : if (i & 4) {
1557 28 : tflags[i].parent_set_sd_type |=
1558 : SEC_DESC_DACL_PROTECTED;
1559 28 : torture_comment(tctx, "PROTECTED, ");
1560 28 : tflags[i].parent_get_sd_type |=
1561 : SEC_DESC_DACL_PROTECTED;
1562 : }
1563 60 : if (i & 8) {
1564 28 : tflags[i].parent_set_ace_inherit |=
1565 : SEC_ACE_FLAG_INHERITED_ACE;
1566 28 : torture_comment(tctx, "INHERITED, ");
1567 28 : tflags[i].parent_get_ace_inherit |=
1568 : SEC_ACE_FLAG_INHERITED_ACE;
1569 : }
1570 :
1571 60 : if ((tflags[i].parent_set_sd_type &
1572 : (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) ==
1573 : (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) {
1574 12 : tflags[i].parent_get_sd_type |=
1575 : SEC_DESC_DACL_AUTO_INHERITED;
1576 12 : tflags[i].child_get_sd_type |=
1577 : SEC_DESC_DACL_AUTO_INHERITED;
1578 12 : tflags[i].child_get_ace_inherit |=
1579 : SEC_ACE_FLAG_INHERITED_ACE;
1580 12 : torture_comment(tctx, " ... parent is AUTO INHERITED");
1581 : }
1582 :
1583 60 : if (tflags[i].parent_set_ace_inherit &
1584 : SEC_ACE_FLAG_INHERITED_ACE) {
1585 28 : tflags[i].parent_get_ace_inherit =
1586 : SEC_ACE_FLAG_INHERITED_ACE;
1587 28 : torture_comment(tctx, " ... parent ACE is INHERITED");
1588 : }
1589 :
1590 60 : torture_comment(tctx, "\n");
1591 : }
1592 :
1593 4 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
1594 0 : return false;
1595 :
1596 4 : torture_comment(tctx, "TESTING ACL INHERITANCE FLAGS\n");
1597 :
1598 4 : ZERO_STRUCT(io);
1599 4 : io.level = RAW_OPEN_SMB2;
1600 4 : io.in.create_flags = 0;
1601 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1602 4 : io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1603 4 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1604 4 : io.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
1605 4 : io.in.alloc_size = 0;
1606 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1607 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
1608 4 : io.in.security_flags = 0;
1609 4 : io.in.fname = dname;
1610 :
1611 4 : torture_comment(tctx, "creating initial directory %s\n", dname);
1612 4 : status = smb2_create(tree, tctx, &io);
1613 4 : CHECK_STATUS(status, NT_STATUS_OK);
1614 4 : handle = io.out.file.handle;
1615 :
1616 4 : torture_comment(tctx, "getting original sd\n");
1617 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1618 4 : q.query_secdesc.in.file.handle = handle;
1619 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1620 4 : status = smb2_getinfo_file(tree, tctx, &q);
1621 4 : CHECK_STATUS(status, NT_STATUS_OK);
1622 4 : sd_orig = q.query_secdesc.out.sd;
1623 :
1624 4 : owner_sid = sd_orig->owner_sid;
1625 4 : owner_sid_string = dom_sid_string(tctx, sd_orig->owner_sid);
1626 4 : torture_comment(tctx, "owner_sid is %s\n", owner_sid_string);
1627 :
1628 68 : for (i=0; i < ARRAY_SIZE(tflags); i++) {
1629 64 : torture_comment(tctx, "setting a new sd on directory, pass #%d\n", i);
1630 :
1631 64 : sd = security_descriptor_dacl_create(tctx,
1632 64 : tflags[i].parent_set_sd_type,
1633 : NULL, NULL,
1634 : owner_sid_string,
1635 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1636 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1637 : SEC_ACE_FLAG_OBJECT_INHERIT |
1638 : SEC_ACE_FLAG_CONTAINER_INHERIT |
1639 64 : tflags[i].parent_set_ace_inherit,
1640 : SID_WORLD,
1641 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1642 : SEC_FILE_ALL | SEC_STD_ALL,
1643 : 0,
1644 : NULL);
1645 64 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1646 64 : set.set_secdesc.in.file.handle = handle;
1647 64 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1648 64 : set.set_secdesc.in.sd = sd;
1649 64 : status = smb2_setinfo_file(tree, &set);
1650 64 : CHECK_STATUS(status, NT_STATUS_OK);
1651 :
1652 : /*
1653 : * Check DACL we just set, except change the bits to what they
1654 : * should be.
1655 : */
1656 64 : torture_comment(tctx, " checking new sd\n");
1657 :
1658 : /* REQ bit should always be false. */
1659 64 : sd->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
1660 :
1661 64 : if ((tflags[i].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
1662 52 : sd->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
1663 :
1664 64 : q.query_secdesc.in.file.handle = handle;
1665 64 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
1666 64 : status = smb2_getinfo_file(tree, tctx, &q);
1667 64 : CHECK_STATUS(status, NT_STATUS_OK);
1668 64 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
1669 :
1670 : /* Create file. */
1671 64 : torture_comment(tctx, " creating file %s\n", fname1);
1672 64 : io.in.fname = fname1;
1673 64 : io.in.create_options = 0;
1674 64 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1675 64 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1676 64 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1677 64 : status = smb2_create(tree, tctx, &io);
1678 64 : CHECK_STATUS(status, NT_STATUS_OK);
1679 64 : handle2 = io.out.file.handle;
1680 64 : CHECK_ACCESS_FLAGS(handle2, SEC_RIGHTS_FILE_ALL);
1681 :
1682 64 : q.query_secdesc.in.file.handle = handle2;
1683 64 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1684 64 : status = smb2_getinfo_file(tree, tctx, &q);
1685 64 : CHECK_STATUS(status, NT_STATUS_OK);
1686 :
1687 64 : torture_comment(tctx, " checking sd on file %s\n", fname1);
1688 64 : sd2 = security_descriptor_dacl_create(tctx,
1689 64 : tflags[i].child_get_sd_type,
1690 : owner_sid_string, NULL,
1691 : owner_sid_string,
1692 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1693 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1694 : tflags[i].child_get_ace_inherit,
1695 : NULL);
1696 64 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1697 :
1698 : /*
1699 : * Set new sd on file ... prove that the bits have nothing to
1700 : * do with the parents bits when manually setting an ACL. The
1701 : * _AUTO_INHERITED bit comes directly from the ACL set.
1702 : */
1703 1088 : for (j = 0; j < ARRAY_SIZE(tflags); j++) {
1704 1024 : torture_comment(tctx, " setting new file sd, pass #%d\n", j);
1705 :
1706 : /* Change sd type. */
1707 1024 : sd2->type &= ~(SEC_DESC_DACL_AUTO_INHERITED |
1708 : SEC_DESC_DACL_AUTO_INHERIT_REQ |
1709 : SEC_DESC_DACL_PROTECTED);
1710 1024 : sd2->type |= tflags[j].parent_set_sd_type;
1711 :
1712 1024 : sd2->dacl->aces[0].flags &=
1713 : ~SEC_ACE_FLAG_INHERITED_ACE;
1714 1024 : sd2->dacl->aces[0].flags |=
1715 1024 : tflags[j].parent_set_ace_inherit;
1716 :
1717 1024 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1718 1024 : set.set_secdesc.in.file.handle = handle2;
1719 1024 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1720 1024 : set.set_secdesc.in.sd = sd2;
1721 1024 : status = smb2_setinfo_file(tree, &set);
1722 1024 : CHECK_STATUS(status, NT_STATUS_OK);
1723 :
1724 : /* Check DACL we just set. */
1725 1024 : sd2->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
1726 1024 : if ((tflags[j].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
1727 832 : sd2->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
1728 :
1729 1024 : q.query_secdesc.in.file.handle = handle2;
1730 1024 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1731 1024 : status = smb2_getinfo_file(tree, tctx, &q);
1732 1024 : CHECK_STATUS(status, NT_STATUS_OK);
1733 :
1734 1024 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1735 :
1736 : /*
1737 : * Check that changing owner doesn't affect SD flags.
1738 : *
1739 : * Do this by first changing owner to world and then
1740 : * back to the original owner. Afterwards compare SD,
1741 : * should be the same.
1742 : */
1743 1024 : owner_sd->owner_sid = &world_sid;
1744 1024 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1745 1024 : set.set_secdesc.in.file.handle = handle2;
1746 1024 : set.set_secdesc.in.secinfo_flags = SECINFO_OWNER;
1747 1024 : set.set_secdesc.in.sd = owner_sd;
1748 1024 : status = smb2_setinfo_file(tree, &set);
1749 1024 : CHECK_STATUS(status, NT_STATUS_OK);
1750 :
1751 1024 : owner_sd->owner_sid = owner_sid;
1752 1024 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1753 1024 : set.set_secdesc.in.file.handle = handle2;
1754 1024 : set.set_secdesc.in.secinfo_flags = SECINFO_OWNER;
1755 1024 : set.set_secdesc.in.sd = owner_sd;
1756 1024 : status = smb2_setinfo_file(tree, &set);
1757 1024 : CHECK_STATUS(status, NT_STATUS_OK);
1758 :
1759 1024 : q.query_secdesc.in.file.handle = handle2;
1760 1024 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1761 1024 : status = smb2_getinfo_file(tree, tctx, &q);
1762 1024 : CHECK_STATUS(status, NT_STATUS_OK);
1763 :
1764 1024 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1765 1024 : torture_assert_goto(tctx, ret, ret, done, "CHECK_SECURITY_DESCRIPTOR failed\n");
1766 : }
1767 :
1768 64 : smb2_util_close(tree, handle2);
1769 64 : smb2_util_unlink(tree, fname1);
1770 : }
1771 :
1772 4 : done:
1773 4 : smb2_util_close(tree, handle);
1774 4 : smb2_deltree(tree, BASEDIR);
1775 4 : smb2_tdis(tree);
1776 4 : smb2_logoff(tree->session);
1777 4 : return ret;
1778 : }
1779 :
1780 : /*
1781 : test dynamic acl inheritance
1782 : Note: This test was copied from raw/acls.c.
1783 : */
1784 4 : static bool test_inheritance_dynamic(struct torture_context *tctx,
1785 : struct smb2_tree *tree)
1786 : {
1787 0 : NTSTATUS status;
1788 0 : struct smb2_create io;
1789 4 : const char *dname = BASEDIR "\\inheritance";
1790 4 : const char *fname1 = BASEDIR "\\inheritance\\testfile";
1791 4 : bool ret = true;
1792 4 : struct smb2_handle handle = {{0}};
1793 4 : struct smb2_handle handle2 = {{0}};
1794 0 : union smb_fileinfo q;
1795 0 : union smb_setfileinfo set;
1796 4 : struct security_descriptor *sd, *sd_orig=NULL;
1797 0 : const char *owner_sid;
1798 :
1799 4 : torture_comment(tctx, "TESTING DYNAMIC ACL INHERITANCE\n");
1800 :
1801 4 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
1802 0 : return false;
1803 :
1804 4 : ZERO_STRUCT(io);
1805 4 : io.level = RAW_OPEN_SMB2;
1806 4 : io.in.create_flags = 0;
1807 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
1808 4 : io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1809 4 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1810 4 : io.in.share_access = 0;
1811 4 : io.in.alloc_size = 0;
1812 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1813 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
1814 4 : io.in.security_flags = 0;
1815 4 : io.in.fname = dname;
1816 :
1817 4 : status = smb2_create(tree, tctx, &io);
1818 4 : CHECK_STATUS(status, NT_STATUS_OK);
1819 4 : handle = io.out.file.handle;
1820 :
1821 4 : torture_comment(tctx, "get the original sd\n");
1822 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1823 4 : q.query_secdesc.in.file.handle = handle;
1824 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1825 4 : status = smb2_getinfo_file(tree, tctx, &q);
1826 4 : CHECK_STATUS(status, NT_STATUS_OK);
1827 4 : sd_orig = q.query_secdesc.out.sd;
1828 :
1829 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1830 :
1831 4 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
1832 :
1833 4 : sd = security_descriptor_dacl_create(tctx,
1834 : 0, NULL, NULL,
1835 : owner_sid,
1836 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1837 : SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE,
1838 : SEC_ACE_FLAG_OBJECT_INHERIT,
1839 : NULL);
1840 4 : sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
1841 :
1842 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1843 4 : set.set_secdesc.in.file.handle = handle;
1844 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1845 4 : set.set_secdesc.in.sd = sd;
1846 4 : status = smb2_setinfo_file(tree, &set);
1847 4 : CHECK_STATUS(status, NT_STATUS_OK);
1848 :
1849 4 : torture_comment(tctx, "create a file with an inherited acl\n");
1850 4 : io.in.fname = fname1;
1851 4 : io.in.create_options = 0;
1852 4 : io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
1853 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1854 4 : status = smb2_create(tree, tctx, &io);
1855 4 : CHECK_STATUS(status, NT_STATUS_OK);
1856 4 : handle2 = io.out.file.handle;
1857 4 : smb2_util_close(tree, handle2);
1858 :
1859 4 : torture_comment(tctx, "try and access file with base rights - should be OK\n");
1860 4 : io.in.desired_access = SEC_FILE_WRITE_DATA;
1861 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1862 4 : status = smb2_create(tree, tctx, &io);
1863 4 : CHECK_STATUS(status, NT_STATUS_OK);
1864 4 : handle2 = io.out.file.handle;
1865 4 : smb2_util_close(tree, handle2);
1866 :
1867 4 : torture_comment(tctx, "try and access file with extra rights - should be denied\n");
1868 4 : io.in.desired_access = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
1869 4 : status = smb2_create(tree, tctx, &io);
1870 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1871 :
1872 4 : torture_comment(tctx, "update parent sd\n");
1873 4 : sd = security_descriptor_dacl_create(tctx,
1874 : 0, NULL, NULL,
1875 : owner_sid,
1876 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1877 : SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE,
1878 : SEC_ACE_FLAG_OBJECT_INHERIT,
1879 : NULL);
1880 4 : sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
1881 :
1882 4 : set.set_secdesc.in.sd = sd;
1883 4 : status = smb2_setinfo_file(tree, &set);
1884 4 : CHECK_STATUS(status, NT_STATUS_OK);
1885 :
1886 4 : torture_comment(tctx, "try and access file with base rights - should be OK\n");
1887 4 : io.in.desired_access = SEC_FILE_WRITE_DATA;
1888 4 : status = smb2_create(tree, tctx, &io);
1889 4 : CHECK_STATUS(status, NT_STATUS_OK);
1890 4 : handle2 = io.out.file.handle;
1891 4 : smb2_util_close(tree, handle2);
1892 :
1893 :
1894 4 : torture_comment(tctx, "try and access now - should be OK if dynamic inheritance works\n");
1895 4 : io.in.desired_access = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
1896 4 : status = smb2_create(tree, tctx, &io);
1897 4 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1898 4 : torture_comment(tctx, "Server does not have dynamic inheritance\n");
1899 : }
1900 4 : if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1901 0 : torture_comment(tctx, "Server does have dynamic inheritance\n");
1902 : }
1903 4 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1904 :
1905 4 : smb2_util_unlink(tree, fname1);
1906 :
1907 4 : done:
1908 4 : torture_comment(tctx, "put back original sd\n");
1909 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1910 4 : set.set_secdesc.in.file.handle = handle;
1911 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1912 4 : set.set_secdesc.in.sd = sd_orig;
1913 4 : status = smb2_setinfo_file(tree, &set);
1914 :
1915 4 : smb2_util_close(tree, handle);
1916 4 : smb2_util_rmdir(tree, dname);
1917 4 : smb2_deltree(tree, BASEDIR);
1918 4 : smb2_tdis(tree);
1919 4 : smb2_logoff(tree->session);
1920 :
1921 4 : return ret;
1922 : }
1923 :
1924 : #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
1925 : if (!(bits & desired_64)) {\
1926 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
1927 : action; \
1928 : } else { \
1929 : CHECK_STATUS(status, NT_STATUS_OK); \
1930 : } \
1931 : } while (0)
1932 :
1933 : #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
1934 : if (NT_STATUS_IS_OK(status)) { \
1935 : if (!(granted & access)) {\
1936 : ret = false; \
1937 : torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
1938 : __location__, nt_errstr(status), access, granted, desired); \
1939 : goto done; \
1940 : } \
1941 : } else { \
1942 : if (granted & access) {\
1943 : ret = false; \
1944 : torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
1945 : __location__, nt_errstr(status), access, granted, desired); \
1946 : goto done; \
1947 : } \
1948 : } \
1949 : CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
1950 : } while (0)
1951 :
1952 : #if 0
1953 : /* test what access mask is needed for getting and setting security_descriptors */
1954 : /* Note: This test was copied from raw/acls.c. */
1955 : static bool test_sd_get_set(struct torture_context *tctx, struct smb2_tree *tree)
1956 : {
1957 : NTSTATUS status;
1958 : bool ret = true;
1959 : struct smb2_create io;
1960 : union smb_fileinfo fi;
1961 : union smb_setfileinfo si;
1962 : struct security_descriptor *sd;
1963 : struct security_descriptor *sd_owner = NULL;
1964 : struct security_descriptor *sd_group = NULL;
1965 : struct security_descriptor *sd_dacl = NULL;
1966 : struct security_descriptor *sd_sacl = NULL;
1967 : struct smb2_handle handle;
1968 : const char *fname = BASEDIR "\\sd_get_set.txt";
1969 : uint64_t desired_64;
1970 : uint32_t desired = 0, granted;
1971 : int i = 0;
1972 : #define NO_BITS_HACK (((uint64_t)1)<<32)
1973 : uint64_t open_bits =
1974 : SEC_MASK_GENERIC |
1975 : SEC_FLAG_SYSTEM_SECURITY |
1976 : SEC_FLAG_MAXIMUM_ALLOWED |
1977 : SEC_STD_ALL |
1978 : SEC_FILE_ALL |
1979 : NO_BITS_HACK;
1980 : uint64_t get_owner_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1981 : uint64_t set_owner_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
1982 : uint64_t get_group_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1983 : uint64_t set_group_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
1984 : uint64_t get_dacl_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1985 : uint64_t set_dacl_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_DAC;
1986 : uint64_t get_sacl_bits = SEC_FLAG_SYSTEM_SECURITY;
1987 : uint64_t set_sacl_bits = SEC_FLAG_SYSTEM_SECURITY;
1988 :
1989 : if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
1990 : return false;
1991 :
1992 : torture_comment(tctx, "TESTING ACCESS MASKS FOR SD GET/SET\n");
1993 :
1994 : /* first create a file with full access for everyone */
1995 : sd = security_descriptor_dacl_create(tctx,
1996 : 0, SID_NT_ANONYMOUS, SID_BUILTIN_USERS,
1997 : SID_WORLD,
1998 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1999 : SEC_GENERIC_ALL,
2000 : 0,
2001 : NULL);
2002 : sd->type |= SEC_DESC_SACL_PRESENT;
2003 : sd->sacl = NULL;
2004 : ZERO_STRUCT(io);
2005 : io.level = RAW_OPEN_SMB2;
2006 : io.in.create_flags = 0;
2007 : io.in.desired_access = SEC_GENERIC_ALL;
2008 : io.in.create_options = 0;
2009 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2010 : io.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2011 : io.in.alloc_size = 0;
2012 : io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2013 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
2014 : io.in.security_flags = 0;
2015 : io.in.fname = fname;
2016 : io.in.sec_desc = sd;
2017 : status = smb2_create(tree, tctx, &io);
2018 : CHECK_STATUS(status, NT_STATUS_OK);
2019 : handle = io.out.file.handle;
2020 :
2021 : status = smb2_util_close(tree, handle);
2022 : CHECK_STATUS(status, NT_STATUS_OK);
2023 :
2024 : /*
2025 : * now try each access_mask bit and no bit at all in a loop
2026 : * and see what's allowed
2027 : * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
2028 : */
2029 : for (i=0; i <= 32; i++) {
2030 : desired_64 = ((uint64_t)1) << i;
2031 : desired = (uint32_t)desired_64;
2032 :
2033 : /* first open the file with the desired access */
2034 : io.level = RAW_OPEN_SMB2;
2035 : io.in.desired_access = desired;
2036 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
2037 : status = smb2_create(tree, tctx, &io);
2038 : CHECK_STATUS_FOR_BIT_ACTION(status, open_bits, goto next);
2039 : handle = io.out.file.handle;
2040 :
2041 : /* then check what access was granted */
2042 : fi.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
2043 : fi.access_information.in.file.handle = handle;
2044 : status = smb2_getinfo_file(tree, tctx, &fi);
2045 : CHECK_STATUS(status, NT_STATUS_OK);
2046 : granted = fi.access_information.out.access_flags;
2047 :
2048 : /* test the owner */
2049 : ZERO_STRUCT(fi);
2050 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2051 : fi.query_secdesc.in.file.handle = handle;
2052 : fi.query_secdesc.in.secinfo_flags = SECINFO_OWNER;
2053 : status = smb2_getinfo_file(tree, tctx, &fi);
2054 : CHECK_STATUS_FOR_BIT(status, get_owner_bits, SEC_STD_READ_CONTROL);
2055 : if (fi.query_secdesc.out.sd) {
2056 : sd_owner = fi.query_secdesc.out.sd;
2057 : } else if (!sd_owner) {
2058 : sd_owner = sd;
2059 : }
2060 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2061 : si.set_secdesc.in.file.handle = handle;
2062 : si.set_secdesc.in.secinfo_flags = SECINFO_OWNER;
2063 : si.set_secdesc.in.sd = sd_owner;
2064 : status = smb2_setinfo_file(tree, &si);
2065 : CHECK_STATUS_FOR_BIT(status, set_owner_bits, SEC_STD_WRITE_OWNER);
2066 :
2067 : /* test the group */
2068 : ZERO_STRUCT(fi);
2069 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2070 : fi.query_secdesc.in.file.handle = handle;
2071 : fi.query_secdesc.in.secinfo_flags = SECINFO_GROUP;
2072 : status = smb2_getinfo_file(tree, tctx, &fi);
2073 : CHECK_STATUS_FOR_BIT(status, get_group_bits, SEC_STD_READ_CONTROL);
2074 : if (fi.query_secdesc.out.sd) {
2075 : sd_group = fi.query_secdesc.out.sd;
2076 : } else if (!sd_group) {
2077 : sd_group = sd;
2078 : }
2079 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2080 : si.set_secdesc.in.file.handle = handle;
2081 : si.set_secdesc.in.secinfo_flags = SECINFO_GROUP;
2082 : si.set_secdesc.in.sd = sd_group;
2083 : status = smb2_setinfo_file(tree, &si);
2084 : CHECK_STATUS_FOR_BIT(status, set_group_bits, SEC_STD_WRITE_OWNER);
2085 :
2086 : /* test the DACL */
2087 : ZERO_STRUCT(fi);
2088 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2089 : fi.query_secdesc.in.file.handle = handle;
2090 : fi.query_secdesc.in.secinfo_flags = SECINFO_DACL;
2091 : status = smb2_getinfo_file(tree, tctx, &fi);
2092 : CHECK_STATUS_FOR_BIT(status, get_dacl_bits, SEC_STD_READ_CONTROL);
2093 : if (fi.query_secdesc.out.sd) {
2094 : sd_dacl = fi.query_secdesc.out.sd;
2095 : } else if (!sd_dacl) {
2096 : sd_dacl = sd;
2097 : }
2098 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2099 : si.set_secdesc.in.file.handle = handle;
2100 : si.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2101 : si.set_secdesc.in.sd = sd_dacl;
2102 : status = smb2_setinfo_file(tree, &si);
2103 : CHECK_STATUS_FOR_BIT(status, set_dacl_bits, SEC_STD_WRITE_DAC);
2104 :
2105 : /* test the SACL */
2106 : ZERO_STRUCT(fi);
2107 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2108 : fi.query_secdesc.in.file.handle = handle;
2109 : fi.query_secdesc.in.secinfo_flags = SECINFO_SACL;
2110 : status = smb2_getinfo_file(tree, tctx, &fi);
2111 : CHECK_STATUS_FOR_BIT(status, get_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
2112 : if (fi.query_secdesc.out.sd) {
2113 : sd_sacl = fi.query_secdesc.out.sd;
2114 : } else if (!sd_sacl) {
2115 : sd_sacl = sd;
2116 : }
2117 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2118 : si.set_secdesc.in.file.handle = handle;
2119 : si.set_secdesc.in.secinfo_flags = SECINFO_SACL;
2120 : si.set_secdesc.in.sd = sd_sacl;
2121 : status = smb2_setinfo_file(tree, &si);
2122 : CHECK_STATUS_FOR_BIT(status, set_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
2123 :
2124 : /* close the handle */
2125 : status = smb2_util_close(tree, handle);
2126 : CHECK_STATUS(status, NT_STATUS_OK);
2127 : next:
2128 : continue;
2129 : }
2130 :
2131 : done:
2132 : smb2_util_close(tree, handle);
2133 : smb2_util_unlink(tree, fname);
2134 : smb2_deltree(tree, BASEDIR);
2135 : smb2_tdis(tree);
2136 : smb2_logoff(tree->session);
2137 :
2138 : return ret;
2139 : }
2140 : #endif
2141 :
2142 4 : static bool test_access_based(struct torture_context *tctx,
2143 : struct smb2_tree *tree)
2144 : {
2145 4 : struct smb2_tree *tree1 = NULL;
2146 0 : NTSTATUS status;
2147 0 : struct smb2_create io;
2148 4 : const char *fname = BASEDIR "\\testfile";
2149 4 : bool ret = true;
2150 0 : struct smb2_handle fhandle, dhandle;
2151 0 : union smb_fileinfo q;
2152 0 : union smb_setfileinfo set;
2153 4 : struct security_descriptor *sd, *sd_orig=NULL;
2154 0 : const char *owner_sid;
2155 4 : uint32_t flags = 0;
2156 : /*
2157 : * Can't test without SEC_STD_READ_CONTROL as we
2158 : * own the file and implicitly have SEC_STD_READ_CONTROL.
2159 : */
2160 4 : uint32_t access_masks[] = {
2161 : /* Full READ access. */
2162 : SEC_STD_READ_CONTROL|FILE_READ_DATA|
2163 : FILE_READ_ATTRIBUTES|FILE_READ_EA,
2164 :
2165 : /* Missing FILE_READ_EA. */
2166 : SEC_STD_READ_CONTROL|FILE_READ_DATA|
2167 : FILE_READ_ATTRIBUTES,
2168 :
2169 : /* Missing FILE_READ_ATTRIBUTES. */
2170 : SEC_STD_READ_CONTROL|FILE_READ_DATA|
2171 : FILE_READ_EA,
2172 :
2173 : /* Missing FILE_READ_DATA. */
2174 : SEC_STD_READ_CONTROL|
2175 : FILE_READ_ATTRIBUTES|FILE_READ_EA,
2176 : };
2177 0 : unsigned int i;
2178 0 : unsigned int count;
2179 0 : struct smb2_find f;
2180 0 : union smb_search_data *d;
2181 :
2182 4 : ZERO_STRUCT(fhandle);
2183 4 : ZERO_STRUCT(dhandle);
2184 :
2185 4 : if (!torture_smb2_con_share(tctx, "hideunread", &tree1)) {
2186 0 : torture_result(tctx, TORTURE_FAIL, "(%s) Unable to connect "
2187 : "to share 'hideunread'\n",
2188 : __location__);
2189 0 : ret = false;
2190 0 : goto done;
2191 : }
2192 :
2193 4 : flags = smb2cli_tcon_flags(tree1->smbXcli);
2194 :
2195 4 : smb2_util_unlink(tree1, fname);
2196 4 : smb2_deltree(tree1, BASEDIR);
2197 :
2198 4 : torture_comment(tctx, "TESTING ACCESS BASED ENUMERATION\n");
2199 :
2200 4 : if ((flags & SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM)==0) {
2201 0 : torture_result(tctx, TORTURE_FAIL, "(%s) No access enumeration "
2202 : "on share 'hideunread'\n",
2203 : __location__);
2204 0 : ret = false;
2205 0 : goto done;
2206 : }
2207 :
2208 4 : if (!smb2_util_setup_dir(tctx, tree1, BASEDIR)) {
2209 0 : torture_result(tctx, TORTURE_FAIL, "(%s) Unable to setup %s\n",
2210 : __location__, BASEDIR);
2211 0 : ret = false;
2212 0 : goto done;
2213 : }
2214 :
2215 : /* Get a handle to the BASEDIR directory. */
2216 4 : status = torture_smb2_testdir(tree1, BASEDIR, &dhandle);
2217 4 : CHECK_STATUS(status, NT_STATUS_OK);
2218 4 : smb2_util_close(tree1, dhandle);
2219 4 : ZERO_STRUCT(dhandle);
2220 :
2221 4 : ZERO_STRUCT(io);
2222 4 : io.level = RAW_OPEN_SMB2;
2223 4 : io.in.create_flags = 0;
2224 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
2225 4 : io.in.create_options = 0;
2226 4 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2227 4 : io.in.share_access = 0;
2228 4 : io.in.alloc_size = 0;
2229 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
2230 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
2231 4 : io.in.security_flags = 0;
2232 4 : io.in.fname = fname;
2233 :
2234 4 : status = smb2_create(tree1, tctx, &io);
2235 4 : CHECK_STATUS(status, NT_STATUS_OK);
2236 4 : fhandle = io.out.file.handle;
2237 :
2238 4 : torture_comment(tctx, "get the original sd\n");
2239 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2240 4 : q.query_secdesc.in.file.handle = fhandle;
2241 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2242 4 : status = smb2_getinfo_file(tree1, tctx, &q);
2243 4 : CHECK_STATUS(status, NT_STATUS_OK);
2244 4 : sd_orig = q.query_secdesc.out.sd;
2245 :
2246 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2247 :
2248 4 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
2249 :
2250 : /* Setup for the search. */
2251 4 : ZERO_STRUCT(f);
2252 4 : f.in.pattern = "*";
2253 4 : f.in.continue_flags = SMB2_CONTINUE_FLAG_REOPEN;
2254 4 : f.in.max_response_size = 0x1000;
2255 4 : f.in.level = SMB2_FIND_DIRECTORY_INFO;
2256 :
2257 20 : for (i = 0; i < ARRAY_SIZE(access_masks); i++) {
2258 :
2259 16 : sd = security_descriptor_dacl_create(tctx,
2260 : 0, NULL, NULL,
2261 : owner_sid,
2262 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2263 16 : access_masks[i]|SEC_STD_SYNCHRONIZE,
2264 : 0,
2265 : NULL);
2266 :
2267 16 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2268 16 : set.set_secdesc.in.file.handle = fhandle;
2269 16 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2270 16 : set.set_secdesc.in.sd = sd;
2271 16 : status = smb2_setinfo_file(tree1, &set);
2272 16 : CHECK_STATUS(status, NT_STATUS_OK);
2273 :
2274 : /* Now see if we can see the file in a directory listing. */
2275 :
2276 : /* Re-open dhandle. */
2277 16 : status = torture_smb2_testdir(tree1, BASEDIR, &dhandle);
2278 16 : CHECK_STATUS(status, NT_STATUS_OK);
2279 16 : f.in.file.handle = dhandle;
2280 :
2281 16 : count = 0;
2282 16 : d = NULL;
2283 16 : status = smb2_find_level(tree1, tree1, &f, &count, &d);
2284 16 : TALLOC_FREE(d);
2285 :
2286 16 : CHECK_STATUS(status, NT_STATUS_OK);
2287 :
2288 16 : smb2_util_close(tree1, dhandle);
2289 16 : ZERO_STRUCT(dhandle);
2290 :
2291 16 : if (i == 0) {
2292 : /* We should see the first sd. */
2293 4 : if (count != 3) {
2294 0 : torture_result(tctx, TORTURE_FAIL,
2295 : "(%s) Normal SD - Unable "
2296 : "to see file %s\n",
2297 : __location__,
2298 : BASEDIR);
2299 0 : ret = false;
2300 0 : goto done;
2301 : }
2302 : } else {
2303 : /* But no others. */
2304 12 : if (count != 2) {
2305 0 : torture_result(tctx, TORTURE_FAIL,
2306 : "(%s) SD 0x%x - can "
2307 : "see file %s\n",
2308 : __location__,
2309 : access_masks[i],
2310 : BASEDIR);
2311 0 : ret = false;
2312 0 : goto done;
2313 : }
2314 : }
2315 : }
2316 :
2317 4 : done:
2318 :
2319 4 : if (tree1) {
2320 4 : smb2_util_close(tree1, fhandle);
2321 4 : smb2_util_close(tree1, dhandle);
2322 4 : smb2_util_unlink(tree1, fname);
2323 4 : smb2_deltree(tree1, BASEDIR);
2324 4 : smb2_tdis(tree1);
2325 4 : smb2_logoff(tree1->session);
2326 : }
2327 4 : smb2_tdis(tree);
2328 4 : smb2_logoff(tree->session);
2329 4 : return ret;
2330 : }
2331 :
2332 : /*
2333 : * test Owner Rights, S-1-3-4
2334 : */
2335 4 : static bool test_owner_rights(struct torture_context *tctx,
2336 : struct smb2_tree *tree)
2337 : {
2338 4 : const char *fname = BASEDIR "\\owner_right.txt";
2339 0 : struct smb2_create cr;
2340 4 : struct smb2_handle handle = {{0}};
2341 0 : union smb_fileinfo gi;
2342 0 : union smb_setfileinfo si;
2343 4 : struct security_descriptor *sd_orig = NULL;
2344 4 : struct security_descriptor *sd = NULL;
2345 4 : const char *owner_sid = NULL;
2346 0 : NTSTATUS mxac_status;
2347 0 : NTSTATUS status;
2348 4 : bool ret = true;
2349 :
2350 4 : smb2_deltree(tree, BASEDIR);
2351 :
2352 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2353 4 : torture_assert_goto(tctx, ret, ret, done,
2354 : "smb2_util_setup_dir failed\n");
2355 :
2356 4 : torture_comment(tctx, "TESTING OWNER RIGHTS\n");
2357 :
2358 4 : cr = (struct smb2_create) {
2359 : .in.desired_access = SEC_STD_READ_CONTROL |
2360 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2361 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2362 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2363 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2364 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2365 : .in.fname = fname,
2366 : };
2367 :
2368 4 : status = smb2_create(tree, tctx, &cr);
2369 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2370 : "smb2_create failed\n");
2371 4 : handle = cr.out.file.handle;
2372 :
2373 4 : torture_comment(tctx, "get the original sd\n");
2374 :
2375 4 : gi = (union smb_fileinfo) {
2376 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2377 : .query_secdesc.in.file.handle = handle,
2378 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2379 : };
2380 :
2381 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2382 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2383 : "smb2_getinfo_file failed\n");
2384 :
2385 4 : sd_orig = gi.query_secdesc.out.sd;
2386 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2387 :
2388 : /*
2389 : * Add a 2 element ACL
2390 : * SEC_RIGHTS_FILE_READ for the owner,
2391 : * SEC_FILE_WRITE_DATA for SID_OWNER_RIGHTS.
2392 : *
2393 : * Proves that the owner and SID_OWNER_RIGHTS
2394 : * ACE entries are additive.
2395 : */
2396 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2397 : owner_sid,
2398 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2399 : SEC_RIGHTS_FILE_READ,
2400 : 0,
2401 : SID_OWNER_RIGHTS,
2402 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2403 : SEC_FILE_WRITE_DATA,
2404 : 0,
2405 : NULL);
2406 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2407 : "SD create failed\n");
2408 :
2409 4 : si = (union smb_setfileinfo) {
2410 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2411 : .set_secdesc.in.file.handle = handle,
2412 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2413 : .set_secdesc.in.sd = sd,
2414 : };
2415 :
2416 4 : status = smb2_setinfo_file(tree, &si);
2417 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2418 : "smb2_setinfo_file failed\n");
2419 :
2420 4 : status = smb2_util_close(tree, handle);
2421 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2422 : "smb2_util_close failed\n");
2423 4 : ZERO_STRUCT(handle);
2424 :
2425 4 : cr = (struct smb2_create) {
2426 : .in.desired_access = SEC_STD_READ_CONTROL,
2427 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2428 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2429 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2430 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2431 : .in.query_maximal_access = true,
2432 : .in.fname = fname,
2433 : };
2434 :
2435 4 : status = smb2_create(tree, tctx, &cr);
2436 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2437 : "smb2_setinfo_file failed\n");
2438 4 : handle = cr.out.file.handle;
2439 :
2440 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2441 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2442 : "smb2_setinfo_file failed\n");
2443 :
2444 : /*
2445 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2446 : * do. Mask it out so the test passes against Samba and Windows.
2447 : */
2448 4 : torture_assert_int_equal_goto(tctx,
2449 : cr.out.maximal_access & ~SEC_STD_DELETE,
2450 : SEC_RIGHTS_FILE_READ |
2451 : SEC_FILE_WRITE_DATA,
2452 : ret, done,
2453 : "Wrong maximum access\n");
2454 :
2455 4 : status = smb2_util_close(tree, handle);
2456 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2457 : "smb2_util_close failed\n");
2458 4 : ZERO_STRUCT(handle);
2459 :
2460 4 : done:
2461 4 : if (!smb2_util_handle_empty(handle)) {
2462 0 : smb2_util_close(tree, handle);
2463 : }
2464 4 : smb2_deltree(tree, BASEDIR);
2465 4 : return ret;
2466 : }
2467 :
2468 : /*
2469 : * test Owner Rights with a leading DENY ACE, S-1-3-4
2470 : */
2471 4 : static bool test_owner_rights_deny(struct torture_context *tctx,
2472 : struct smb2_tree *tree)
2473 : {
2474 4 : const char *fname = BASEDIR "\\owner_right_deny.txt";
2475 0 : struct smb2_create cr;
2476 4 : struct smb2_handle handle = {{0}};
2477 0 : union smb_fileinfo gi;
2478 0 : union smb_setfileinfo si;
2479 4 : struct security_descriptor *sd_orig = NULL;
2480 4 : struct security_descriptor *sd = NULL;
2481 4 : const char *owner_sid = NULL;
2482 0 : NTSTATUS mxac_status;
2483 0 : NTSTATUS status;
2484 4 : bool ret = true;
2485 :
2486 4 : smb2_deltree(tree, BASEDIR);
2487 :
2488 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2489 4 : torture_assert_goto(tctx, ret, ret, done,
2490 : "smb2_util_setup_dir failed\n");
2491 :
2492 4 : torture_comment(tctx, "TESTING OWNER RIGHTS DENY\n");
2493 :
2494 4 : cr = (struct smb2_create) {
2495 : .in.desired_access = SEC_STD_READ_CONTROL |
2496 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2497 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2498 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2499 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2500 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2501 : .in.fname = fname,
2502 : };
2503 :
2504 4 : status = smb2_create(tree, tctx, &cr);
2505 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2506 : "smb2_create failed\n");
2507 4 : handle = cr.out.file.handle;
2508 :
2509 4 : torture_comment(tctx, "get the original sd\n");
2510 :
2511 4 : gi = (union smb_fileinfo) {
2512 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2513 : .query_secdesc.in.file.handle = handle,
2514 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2515 : };
2516 :
2517 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2518 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2519 : "smb2_getinfo_file failed\n");
2520 :
2521 4 : sd_orig = gi.query_secdesc.out.sd;
2522 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2523 :
2524 : /*
2525 : * Add a 2 element ACL
2526 : * DENY SEC_FILE_DATA_READ for SID_OWNER_RIGHTS
2527 : * SEC_FILE_READ_DATA for the owner.
2528 : *
2529 : * Proves that the owner and SID_OWNER_RIGHTS
2530 : * ACE entries are additive.
2531 : */
2532 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2533 : SID_OWNER_RIGHTS,
2534 : SEC_ACE_TYPE_ACCESS_DENIED,
2535 : SEC_FILE_READ_DATA,
2536 : 0,
2537 : owner_sid,
2538 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2539 : SEC_RIGHTS_FILE_READ,
2540 : 0,
2541 : NULL);
2542 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2543 : "SD create failed\n");
2544 :
2545 4 : si = (union smb_setfileinfo) {
2546 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2547 : .set_secdesc.in.file.handle = handle,
2548 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2549 : .set_secdesc.in.sd = sd,
2550 : };
2551 :
2552 4 : status = smb2_setinfo_file(tree, &si);
2553 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2554 : "smb2_setinfo_file failed\n");
2555 :
2556 4 : status = smb2_util_close(tree, handle);
2557 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2558 : "smb2_util_close failed\n");
2559 4 : ZERO_STRUCT(handle);
2560 :
2561 4 : cr = (struct smb2_create) {
2562 : .in.desired_access = SEC_STD_READ_CONTROL,
2563 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2564 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2565 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2566 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2567 : .in.query_maximal_access = true,
2568 : .in.fname = fname,
2569 : };
2570 :
2571 4 : status = smb2_create(tree, tctx, &cr);
2572 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2573 : "smb2_setinfo_file failed\n");
2574 4 : handle = cr.out.file.handle;
2575 :
2576 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2577 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2578 : "smb2_setinfo_file failed\n");
2579 :
2580 : /*
2581 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2582 : * do. Mask it out so the test passes against Samba and Windows.
2583 : */
2584 4 : torture_assert_int_equal_goto(tctx,
2585 : cr.out.maximal_access & ~SEC_STD_DELETE,
2586 : SEC_RIGHTS_FILE_READ & ~SEC_FILE_READ_DATA,
2587 : ret, done,
2588 : "Wrong maximum access\n");
2589 :
2590 4 : status = smb2_util_close(tree, handle);
2591 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2592 : "smb2_util_close failed\n");
2593 4 : ZERO_STRUCT(handle);
2594 :
2595 4 : done:
2596 4 : if (!smb2_util_handle_empty(handle)) {
2597 0 : smb2_util_close(tree, handle);
2598 : }
2599 4 : smb2_deltree(tree, BASEDIR);
2600 4 : return ret;
2601 : }
2602 :
2603 : /*
2604 : * test Owner Rights with a trailing DENY ACE, S-1-3-4
2605 : */
2606 4 : static bool test_owner_rights_deny1(struct torture_context *tctx,
2607 : struct smb2_tree *tree)
2608 : {
2609 4 : const char *fname = BASEDIR "\\owner_right_deny1.txt";
2610 0 : struct smb2_create cr;
2611 4 : struct smb2_handle handle = {{0}};
2612 0 : union smb_fileinfo gi;
2613 0 : union smb_setfileinfo si;
2614 4 : struct security_descriptor *sd_orig = NULL;
2615 4 : struct security_descriptor *sd = NULL;
2616 4 : const char *owner_sid = NULL;
2617 0 : NTSTATUS mxac_status;
2618 0 : NTSTATUS status;
2619 4 : bool ret = true;
2620 :
2621 4 : smb2_deltree(tree, BASEDIR);
2622 :
2623 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2624 4 : torture_assert_goto(tctx, ret, ret, done,
2625 : "smb2_util_setup_dir failed\n");
2626 :
2627 4 : torture_comment(tctx, "TESTING OWNER RIGHTS DENY1\n");
2628 :
2629 4 : cr = (struct smb2_create) {
2630 : .in.desired_access = SEC_STD_READ_CONTROL |
2631 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2632 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2633 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2634 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2635 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2636 : .in.fname = fname,
2637 : };
2638 :
2639 4 : status = smb2_create(tree, tctx, &cr);
2640 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2641 : "smb2_create failed\n");
2642 4 : handle = cr.out.file.handle;
2643 :
2644 4 : torture_comment(tctx, "get the original sd\n");
2645 :
2646 4 : gi = (union smb_fileinfo) {
2647 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2648 : .query_secdesc.in.file.handle = handle,
2649 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2650 : };
2651 :
2652 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2653 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2654 : "smb2_getinfo_file failed\n");
2655 :
2656 4 : sd_orig = gi.query_secdesc.out.sd;
2657 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2658 :
2659 : /*
2660 : * Add a 3 element ACL
2661 : *
2662 : * SEC_RIGHTS_FILE_READ allow for owner.
2663 : * SEC_FILE_WRITE_DATA allow for SID-OWNER-RIGHTS.
2664 : * SEC_FILE_WRITE_DATA|SEC_FILE_READ_DATA) deny for SID-OWNER-RIGHTS.
2665 : *
2666 : * Shows on Windows that trailing DENY entries don't
2667 : * override granted permissions in max access calculations.
2668 : */
2669 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2670 : owner_sid,
2671 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2672 : SEC_RIGHTS_FILE_READ,
2673 : 0,
2674 : SID_OWNER_RIGHTS,
2675 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2676 : SEC_FILE_WRITE_DATA,
2677 : 0,
2678 : SID_OWNER_RIGHTS,
2679 : SEC_ACE_TYPE_ACCESS_DENIED,
2680 : (SEC_FILE_WRITE_DATA|
2681 : SEC_FILE_READ_DATA),
2682 : 0,
2683 : NULL);
2684 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2685 : "SD create failed\n");
2686 :
2687 4 : si = (union smb_setfileinfo) {
2688 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2689 : .set_secdesc.in.file.handle = handle,
2690 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2691 : .set_secdesc.in.sd = sd,
2692 : };
2693 :
2694 4 : status = smb2_setinfo_file(tree, &si);
2695 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2696 : "smb2_setinfo_file failed\n");
2697 :
2698 4 : status = smb2_util_close(tree, handle);
2699 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2700 : "smb2_util_close failed\n");
2701 4 : ZERO_STRUCT(handle);
2702 :
2703 4 : cr = (struct smb2_create) {
2704 : .in.desired_access = SEC_STD_READ_CONTROL,
2705 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2706 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2707 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2708 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2709 : .in.query_maximal_access = true,
2710 : .in.fname = fname,
2711 : };
2712 :
2713 4 : status = smb2_create(tree, tctx, &cr);
2714 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2715 : "smb2_setinfo_file failed\n");
2716 4 : handle = cr.out.file.handle;
2717 :
2718 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2719 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2720 : "smb2_setinfo_file failed\n");
2721 :
2722 : /*
2723 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2724 : * do. Mask it out so the test passes against Samba and Windows.
2725 : */
2726 4 : torture_assert_int_equal_goto(tctx,
2727 : cr.out.maximal_access & ~SEC_STD_DELETE,
2728 : SEC_RIGHTS_FILE_READ | SEC_FILE_WRITE_DATA,
2729 : ret, done,
2730 : "Wrong maximum access\n");
2731 :
2732 4 : status = smb2_util_close(tree, handle);
2733 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2734 : "smb2_util_close failed\n");
2735 4 : ZERO_STRUCT(handle);
2736 :
2737 4 : done:
2738 4 : if (!smb2_util_handle_empty(handle)) {
2739 0 : smb2_util_close(tree, handle);
2740 : }
2741 4 : smb2_deltree(tree, BASEDIR);
2742 4 : return ret;
2743 : }
2744 :
2745 : /*
2746 : * test that shows that a DENY ACE doesn't remove rights granted
2747 : * by a previous ALLOW ACE.
2748 : */
2749 4 : static bool test_deny1(struct torture_context *tctx,
2750 : struct smb2_tree *tree)
2751 : {
2752 4 : const char *fname = BASEDIR "\\test_deny1.txt";
2753 0 : struct smb2_create cr;
2754 4 : struct smb2_handle handle = {{0}};
2755 0 : union smb_fileinfo gi;
2756 0 : union smb_setfileinfo si;
2757 4 : struct security_descriptor *sd_orig = NULL;
2758 4 : struct security_descriptor *sd = NULL;
2759 4 : const char *owner_sid = NULL;
2760 0 : NTSTATUS mxac_status;
2761 0 : NTSTATUS status;
2762 4 : bool ret = true;
2763 :
2764 4 : smb2_deltree(tree, BASEDIR);
2765 :
2766 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2767 4 : torture_assert_goto(tctx, ret, ret, done,
2768 : "smb2_util_setup_dir failed\n");
2769 :
2770 4 : cr = (struct smb2_create) {
2771 : .in.desired_access = SEC_STD_READ_CONTROL |
2772 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2773 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2774 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2775 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2776 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2777 : .in.fname = fname,
2778 : };
2779 :
2780 4 : status = smb2_create(tree, tctx, &cr);
2781 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2782 : "smb2_create failed\n");
2783 4 : handle = cr.out.file.handle;
2784 :
2785 4 : torture_comment(tctx, "get the original sd\n");
2786 :
2787 4 : gi = (union smb_fileinfo) {
2788 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2789 : .query_secdesc.in.file.handle = handle,
2790 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2791 : };
2792 :
2793 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2794 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2795 : "smb2_getinfo_file failed\n");
2796 :
2797 4 : sd_orig = gi.query_secdesc.out.sd;
2798 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2799 :
2800 : /*
2801 : * Add a 2 element ACL
2802 : *
2803 : * SEC_RIGHTS_FILE_READ|SEC_FILE_WRITE_DATA allow for owner.
2804 : * SEC_FILE_WRITE_DATA deny for owner
2805 : *
2806 : * Shows on Windows that trailing DENY entries don't
2807 : * override granted permissions.
2808 : */
2809 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2810 : owner_sid,
2811 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2812 : SEC_RIGHTS_FILE_READ|SEC_FILE_WRITE_DATA,
2813 : 0,
2814 : owner_sid,
2815 : SEC_ACE_TYPE_ACCESS_DENIED,
2816 : SEC_FILE_WRITE_DATA,
2817 : 0,
2818 : NULL);
2819 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2820 : "SD create failed\n");
2821 :
2822 4 : si = (union smb_setfileinfo) {
2823 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2824 : .set_secdesc.in.file.handle = handle,
2825 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2826 : .set_secdesc.in.sd = sd,
2827 : };
2828 :
2829 4 : status = smb2_setinfo_file(tree, &si);
2830 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2831 : "smb2_setinfo_file failed\n");
2832 :
2833 4 : status = smb2_util_close(tree, handle);
2834 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2835 : "smb2_util_close failed\n");
2836 4 : ZERO_STRUCT(handle);
2837 :
2838 4 : cr = (struct smb2_create) {
2839 : .in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_WRITE_DATA,
2840 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2841 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2842 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2843 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2844 : .in.query_maximal_access = true,
2845 : .in.fname = fname,
2846 : };
2847 :
2848 4 : status = smb2_create(tree, tctx, &cr);
2849 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2850 : "smb2_create failed\n");
2851 4 : handle = cr.out.file.handle;
2852 :
2853 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2854 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2855 : "Wrong maximum access status\n");
2856 :
2857 : /*
2858 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2859 : * do. Mask it out so the test passes against Samba and Windows.
2860 : * SEC_STD_WRITE_DAC comes from being the owner.
2861 : */
2862 4 : torture_assert_int_equal_goto(tctx,
2863 : cr.out.maximal_access & ~SEC_STD_DELETE,
2864 : SEC_RIGHTS_FILE_READ |
2865 : SEC_FILE_WRITE_DATA |
2866 : SEC_STD_WRITE_DAC,
2867 : ret, done,
2868 : "Wrong maximum access\n");
2869 :
2870 4 : status = smb2_util_close(tree, handle);
2871 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2872 : "smb2_util_close failed\n");
2873 4 : ZERO_STRUCT(handle);
2874 :
2875 4 : done:
2876 4 : if (!smb2_util_handle_empty(handle)) {
2877 0 : smb2_util_close(tree, handle);
2878 : }
2879 4 : smb2_deltree(tree, BASEDIR);
2880 4 : return ret;
2881 : }
2882 :
2883 : /*
2884 : * test SEC_FLAG_MAXIMUM_ALLOWED with not-granted access
2885 : *
2886 : * When access_mask contains SEC_FLAG_MAXIMUM_ALLOWED, the server must still
2887 : * process other bits from access_mask. Eg if access_mask contains a right that
2888 : * the requester doesn't have, the function must validate that against the
2889 : * effective permissions.
2890 : */
2891 4 : static bool test_mxac_not_granted(struct torture_context *tctx,
2892 : struct smb2_tree *tree)
2893 : {
2894 4 : const char *fname = BASEDIR "\\test_mxac_not_granted.txt";
2895 0 : struct smb2_create cr;
2896 4 : struct smb2_handle handle = {{0}};
2897 0 : union smb_fileinfo gi;
2898 0 : union smb_setfileinfo si;
2899 4 : struct security_descriptor *sd_orig = NULL;
2900 4 : struct security_descriptor *sd = NULL;
2901 4 : const char *owner_sid = NULL;
2902 0 : NTSTATUS status;
2903 4 : bool ret = true;
2904 :
2905 4 : smb2_deltree(tree, BASEDIR);
2906 :
2907 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2908 4 : torture_assert_goto(tctx, ret, ret, done,
2909 : "smb2_util_setup_dir failed\n");
2910 :
2911 4 : torture_comment(tctx, "TESTING OWNER RIGHTS DENY\n");
2912 :
2913 4 : cr = (struct smb2_create) {
2914 : .in.desired_access = SEC_STD_READ_CONTROL |
2915 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2916 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2917 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2918 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2919 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2920 : .in.fname = fname,
2921 : };
2922 :
2923 4 : status = smb2_create(tree, tctx, &cr);
2924 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2925 : "smb2_create failed\n");
2926 4 : handle = cr.out.file.handle;
2927 :
2928 4 : torture_comment(tctx, "get the original sd\n");
2929 :
2930 4 : gi = (union smb_fileinfo) {
2931 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2932 : .query_secdesc.in.file.handle = handle,
2933 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2934 : };
2935 :
2936 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2937 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2938 : "smb2_getinfo_file failed\n");
2939 :
2940 4 : sd_orig = gi.query_secdesc.out.sd;
2941 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2942 :
2943 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2944 : owner_sid,
2945 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2946 : SEC_FILE_READ_DATA,
2947 : 0,
2948 : NULL);
2949 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2950 : "SD create failed\n");
2951 :
2952 4 : si = (union smb_setfileinfo) {
2953 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2954 : .set_secdesc.in.file.handle = handle,
2955 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2956 : .set_secdesc.in.sd = sd,
2957 : };
2958 :
2959 4 : status = smb2_setinfo_file(tree, &si);
2960 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2961 : "smb2_setinfo_file failed\n");
2962 :
2963 4 : status = smb2_util_close(tree, handle);
2964 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2965 : "smb2_util_close failed\n");
2966 4 : ZERO_STRUCT(handle);
2967 :
2968 4 : cr = (struct smb2_create) {
2969 : .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED |
2970 : SEC_FILE_WRITE_DATA,
2971 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2972 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2973 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2974 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2975 : .in.fname = fname,
2976 : };
2977 :
2978 4 : status = smb2_create(tree, tctx, &cr);
2979 4 : torture_assert_ntstatus_equal_goto(tctx, status,
2980 : NT_STATUS_ACCESS_DENIED,
2981 : ret, done,
2982 : "Wrong smb2_create result\n");
2983 :
2984 4 : done:
2985 4 : if (!smb2_util_handle_empty(handle)) {
2986 0 : smb2_util_close(tree, handle);
2987 : }
2988 4 : smb2_deltree(tree, BASEDIR);
2989 4 : return ret;
2990 : }
2991 :
2992 4 : static bool test_overwrite_read_only_file(struct torture_context *tctx,
2993 : struct smb2_tree *tree)
2994 : {
2995 0 : NTSTATUS status;
2996 0 : struct smb2_create c;
2997 4 : const char *fname = BASEDIR "\\test_overwrite_read_only_file.txt";
2998 4 : struct smb2_handle handle = {{0}};
2999 0 : union smb_fileinfo q;
3000 0 : union smb_setfileinfo set;
3001 4 : struct security_descriptor *sd = NULL, *sd_orig = NULL;
3002 4 : const char *owner_sid = NULL;
3003 0 : int i;
3004 4 : bool ret = true;
3005 :
3006 0 : struct tcase {
3007 : int disposition;
3008 : const char *disposition_string;
3009 : NTSTATUS expected_status;
3010 4 : } tcases[] = {
3011 : #define TCASE(d, s) { \
3012 : .disposition = d, \
3013 : .disposition_string = #d, \
3014 : .expected_status = s, \
3015 : }
3016 : TCASE(NTCREATEX_DISP_OPEN, NT_STATUS_OK),
3017 : TCASE(NTCREATEX_DISP_SUPERSEDE, NT_STATUS_ACCESS_DENIED),
3018 : TCASE(NTCREATEX_DISP_OVERWRITE, NT_STATUS_ACCESS_DENIED),
3019 : TCASE(NTCREATEX_DISP_OVERWRITE_IF, NT_STATUS_ACCESS_DENIED),
3020 : };
3021 : #undef TCASE
3022 :
3023 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
3024 4 : torture_assert_goto(tctx, ret, ret, done, "smb2_util_setup_dir not ok");
3025 :
3026 4 : c = (struct smb2_create) {
3027 : .in.desired_access = SEC_STD_READ_CONTROL |
3028 : SEC_STD_WRITE_DAC |
3029 : SEC_STD_WRITE_OWNER,
3030 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3031 : .in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3032 : NTCREATEX_SHARE_ACCESS_WRITE,
3033 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
3034 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3035 : .in.fname = fname,
3036 : };
3037 :
3038 4 : status = smb2_create(tree, tctx, &c);
3039 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3040 : "smb2_create failed\n");
3041 4 : handle = c.out.file.handle;
3042 :
3043 4 : torture_comment(tctx, "get the original sd\n");
3044 :
3045 4 : ZERO_STRUCT(q);
3046 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
3047 4 : q.query_secdesc.in.file.handle = handle;
3048 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
3049 :
3050 4 : status = smb2_getinfo_file(tree, tctx, &q);
3051 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3052 : "smb2_getinfo_file failed\n");
3053 4 : sd_orig = q.query_secdesc.out.sd;
3054 :
3055 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
3056 :
3057 4 : sd = security_descriptor_dacl_create(tctx,
3058 : 0, NULL, NULL,
3059 : owner_sid,
3060 : SEC_ACE_TYPE_ACCESS_ALLOWED,
3061 : SEC_FILE_READ_DATA,
3062 : 0,
3063 : NULL);
3064 :
3065 4 : ZERO_STRUCT(set);
3066 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
3067 4 : set.set_secdesc.in.file.handle = handle;
3068 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
3069 4 : set.set_secdesc.in.sd = sd;
3070 :
3071 4 : status = smb2_setinfo_file(tree, &set);
3072 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3073 : "smb2_setinfo_file failed\n");
3074 :
3075 4 : smb2_util_close(tree, handle);
3076 4 : ZERO_STRUCT(handle);
3077 :
3078 20 : for (i = 0; i < ARRAY_SIZE(tcases); i++) {
3079 16 : torture_comment(tctx, "Verify open with %s disposition\n",
3080 : tcases[i].disposition_string);
3081 :
3082 16 : c = (struct smb2_create) {
3083 16 : .in.create_disposition = tcases[i].disposition,
3084 : .in.desired_access = SEC_FILE_READ_DATA,
3085 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3086 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3087 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3088 : .in.fname = fname,
3089 : };
3090 :
3091 16 : status = smb2_create(tree, tctx, &c);
3092 16 : smb2_util_close(tree, c.out.file.handle);
3093 16 : torture_assert_ntstatus_equal_goto(
3094 : tctx, status, tcases[i].expected_status, ret, done,
3095 : "smb2_create failed\n");
3096 0 : };
3097 :
3098 4 : torture_comment(tctx, "put back original sd\n");
3099 :
3100 4 : c = (struct smb2_create) {
3101 : .in.desired_access = SEC_STD_WRITE_DAC,
3102 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3103 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3104 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
3105 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3106 : .in.fname = fname,
3107 : };
3108 :
3109 4 : status = smb2_create(tree, tctx, &c);
3110 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3111 : "smb2_create failed\n");
3112 4 : handle = c.out.file.handle;
3113 :
3114 4 : ZERO_STRUCT(set);
3115 4 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
3116 4 : set.set_secdesc.in.file.handle = handle;
3117 4 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
3118 4 : set.set_secdesc.in.sd = sd_orig;
3119 :
3120 4 : status = smb2_setinfo_file(tree, &set);
3121 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3122 : "smb2_setinfo_file failed\n");
3123 :
3124 4 : smb2_util_close(tree, handle);
3125 4 : ZERO_STRUCT(handle);
3126 :
3127 4 : done:
3128 4 : smb2_util_close(tree, handle);
3129 4 : smb2_util_unlink(tree, fname);
3130 4 : smb2_deltree(tree, BASEDIR);
3131 4 : return ret;
3132 : }
3133 :
3134 : /*
3135 : basic testing of SMB2 ACLs
3136 : */
3137 2354 : struct torture_suite *torture_smb2_acls_init(TALLOC_CTX *ctx)
3138 : {
3139 2354 : struct torture_suite *suite = torture_suite_create(ctx, "acls");
3140 :
3141 2354 : torture_suite_add_1smb2_test(suite, "CREATOR", test_creator_sid);
3142 2354 : torture_suite_add_1smb2_test(suite, "GENERIC", test_generic_bits);
3143 2354 : torture_suite_add_1smb2_test(suite, "OWNER", test_owner_bits);
3144 2354 : torture_suite_add_1smb2_test(suite, "INHERITANCE", test_inheritance);
3145 2354 : torture_suite_add_1smb2_test(suite, "INHERITFLAGS", test_inheritance_flags);
3146 2354 : torture_suite_add_1smb2_test(suite, "SDFLAGSVSCHOWN", test_sd_flags_vs_chown);
3147 2354 : torture_suite_add_1smb2_test(suite, "DYNAMIC", test_inheritance_dynamic);
3148 : #if 0
3149 : /* XXX This test does not work against XP or Vista. */
3150 : torture_suite_add_1smb2_test(suite, "GETSET", test_sd_get_set);
3151 : #endif
3152 2354 : torture_suite_add_1smb2_test(suite, "ACCESSBASED", test_access_based);
3153 2354 : torture_suite_add_1smb2_test(suite, "OWNER-RIGHTS", test_owner_rights);
3154 2354 : torture_suite_add_1smb2_test(suite, "OWNER-RIGHTS-DENY",
3155 : test_owner_rights_deny);
3156 2354 : torture_suite_add_1smb2_test(suite, "OWNER-RIGHTS-DENY1",
3157 : test_owner_rights_deny1);
3158 2354 : torture_suite_add_1smb2_test(suite, "DENY1",
3159 : test_deny1);
3160 2354 : torture_suite_add_1smb2_test(suite, "MXAC-NOT-GRANTED",
3161 : test_mxac_not_granted);
3162 2354 : torture_suite_add_1smb2_test(suite, "OVERWRITE_READ_ONLY_FILE", test_overwrite_read_only_file);
3163 :
3164 2354 : suite->description = talloc_strdup(suite, "SMB2-ACLS tests");
3165 :
3166 2354 : return suite;
3167 : }
3168 :
3169 2 : static bool test_acls_non_canonical_flags(struct torture_context *tctx,
3170 : struct smb2_tree *tree)
3171 : {
3172 2 : const char *fname = BASEDIR "\\test_acls_non_canonical_flags.txt";
3173 0 : struct smb2_create cr;
3174 2 : struct smb2_handle testdirh = {{0}};
3175 2 : struct smb2_handle handle = {{0}};
3176 0 : union smb_fileinfo gi;
3177 0 : union smb_setfileinfo si;
3178 2 : struct security_descriptor *sd_orig = NULL;
3179 2 : struct security_descriptor *sd = NULL;
3180 0 : NTSTATUS status;
3181 2 : bool ret = true;
3182 :
3183 2 : smb2_deltree(tree, BASEDIR);
3184 :
3185 2 : status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
3186 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3187 : "torture_smb2_testdir failed\n");
3188 :
3189 2 : sd = security_descriptor_dacl_create(tctx,
3190 : SEC_DESC_DACL_AUTO_INHERITED
3191 : | SEC_DESC_DACL_AUTO_INHERIT_REQ,
3192 : NULL,
3193 : NULL,
3194 : SID_WORLD,
3195 : SEC_ACE_TYPE_ACCESS_ALLOWED,
3196 : SEC_RIGHTS_DIR_ALL,
3197 : SEC_ACE_FLAG_OBJECT_INHERIT
3198 : | SEC_ACE_FLAG_CONTAINER_INHERIT,
3199 : NULL);
3200 2 : torture_assert_not_null_goto(tctx, sd, ret, done,
3201 : "SD create failed\n");
3202 :
3203 2 : si = (union smb_setfileinfo) {
3204 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
3205 : .set_secdesc.in.file.handle = testdirh,
3206 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
3207 : .set_secdesc.in.sd = sd,
3208 : };
3209 :
3210 2 : status = smb2_setinfo_file(tree, &si);
3211 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3212 : "smb2_setinfo_file failed\n");
3213 :
3214 2 : gi = (union smb_fileinfo) {
3215 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
3216 : .query_secdesc.in.file.handle = testdirh,
3217 : .query_secdesc.in.secinfo_flags = SECINFO_DACL,
3218 : };
3219 :
3220 2 : status = smb2_getinfo_file(tree, tctx, &gi);
3221 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3222 : "smb2_getinfo_file failed\n");
3223 :
3224 2 : cr = (struct smb2_create) {
3225 : .in.desired_access = SEC_STD_READ_CONTROL |
3226 : SEC_STD_WRITE_DAC,
3227 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3228 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3229 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
3230 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3231 : .in.fname = fname,
3232 : };
3233 :
3234 2 : status = smb2_create(tree, tctx, &cr);
3235 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3236 : "smb2_create failed\n");
3237 2 : handle = cr.out.file.handle;
3238 :
3239 2 : torture_comment(tctx, "get the original sd\n");
3240 :
3241 2 : gi = (union smb_fileinfo) {
3242 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
3243 : .query_secdesc.in.file.handle = handle,
3244 : .query_secdesc.in.secinfo_flags = SECINFO_DACL,
3245 : };
3246 :
3247 2 : status = smb2_getinfo_file(tree, tctx, &gi);
3248 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3249 : "smb2_getinfo_file failed\n");
3250 :
3251 2 : sd_orig = gi.query_secdesc.out.sd;
3252 :
3253 2 : torture_assert_goto(tctx, sd_orig->type & SEC_DESC_DACL_AUTO_INHERITED,
3254 : ret, done, "Missing SEC_DESC_DACL_AUTO_INHERITED\n");
3255 :
3256 : /*
3257 : * SD with SEC_DESC_DACL_AUTO_INHERITED but without
3258 : * SEC_DESC_DACL_AUTO_INHERITED_REQ, so the resulting SD should not have
3259 : * SEC_DESC_DACL_AUTO_INHERITED on a Windows box.
3260 : *
3261 : * But as we're testing against a share with
3262 : *
3263 : * "acl flag inherited canonicalization = no"
3264 : *
3265 : * the resulting SD should have acl flag inherited canonicalization set.
3266 : */
3267 2 : sd = security_descriptor_dacl_create(tctx,
3268 : SEC_DESC_DACL_AUTO_INHERITED,
3269 : NULL,
3270 : NULL,
3271 : SID_WORLD,
3272 : SEC_ACE_TYPE_ACCESS_ALLOWED,
3273 : SEC_FILE_ALL,
3274 : 0,
3275 : NULL);
3276 2 : torture_assert_not_null_goto(tctx, sd, ret, done,
3277 : "SD create failed\n");
3278 :
3279 2 : si = (union smb_setfileinfo) {
3280 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
3281 : .set_secdesc.in.file.handle = handle,
3282 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
3283 : .set_secdesc.in.sd = sd,
3284 : };
3285 :
3286 2 : status = smb2_setinfo_file(tree, &si);
3287 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3288 : "smb2_setinfo_file failed\n");
3289 :
3290 2 : status = smb2_util_close(tree, handle);
3291 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3292 : "smb2_util_close failed\n");
3293 2 : ZERO_STRUCT(handle);
3294 :
3295 2 : cr = (struct smb2_create) {
3296 : .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED ,
3297 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3298 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3299 : .in.create_disposition = NTCREATEX_DISP_OPEN,
3300 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3301 : .in.fname = fname,
3302 : };
3303 :
3304 2 : status = smb2_create(tree, tctx, &cr);
3305 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3306 : "smb2_create failed\n");
3307 2 : handle = cr.out.file.handle;
3308 :
3309 2 : gi = (union smb_fileinfo) {
3310 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
3311 : .query_secdesc.in.file.handle = handle,
3312 : .query_secdesc.in.secinfo_flags = SECINFO_DACL,
3313 : };
3314 :
3315 2 : status = smb2_getinfo_file(tree, tctx, &gi);
3316 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3317 : "smb2_getinfo_file failed\n");
3318 :
3319 2 : sd_orig = gi.query_secdesc.out.sd;
3320 2 : torture_assert_goto(tctx, sd_orig->type & SEC_DESC_DACL_AUTO_INHERITED,
3321 : ret, done, "Missing SEC_DESC_DACL_AUTO_INHERITED\n");
3322 :
3323 2 : done:
3324 2 : if (!smb2_util_handle_empty(handle)) {
3325 2 : smb2_util_close(tree, testdirh);
3326 : }
3327 2 : if (!smb2_util_handle_empty(handle)) {
3328 2 : smb2_util_close(tree, handle);
3329 : }
3330 2 : smb2_deltree(tree, BASEDIR);
3331 2 : return ret;
3332 : }
3333 :
3334 2354 : struct torture_suite *torture_smb2_acls_non_canonical_init(TALLOC_CTX *ctx)
3335 : {
3336 2354 : struct torture_suite *suite = torture_suite_create(ctx, "acls_non_canonical");
3337 :
3338 2354 : torture_suite_add_1smb2_test(suite, "flags", test_acls_non_canonical_flags);
3339 2354 : return suite;
3340 : }
|