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 : NTSTATUS status;
99 : 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 : union smb_fileinfo q;
104 : union smb_setfileinfo set;
105 : struct security_descriptor *sd, *sd_orig, *sd2;
106 : 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 5 : 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 5 : 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 7 : 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 : NTSTATUS status;
301 : 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 : int i;
306 : union smb_fileinfo q;
307 : union smb_setfileinfo set;
308 : struct security_descriptor *sd, *sd_orig, *sd2;
309 : const char *owner_sid;
310 : 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 : 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 7 : 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 7 : 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 7 : 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 5 : 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 5 : 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 5 : 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 : NTSTATUS status;
667 : 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 : int i;
672 : union smb_fileinfo q;
673 : union smb_setfileinfo set;
674 : struct security_descriptor *sd, *sd_orig;
675 : const char *owner_sid;
676 : 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 7 : 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 : NTSTATUS status;
801 : 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 : int i;
809 : union smb_fileinfo q;
810 : union smb_setfileinfo set;
811 4 : struct security_descriptor *sd, *sd2, *sd_orig=NULL, *sd_def1, *sd_def2;
812 : const char *owner_sid;
813 : const struct dom_sid *creator_owner;
814 : 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 16 : 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 56 : 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 56 : if (q.query_secdesc.out.sd->dacl == NULL ||
1030 56 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1031 56 : 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 56 : 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 80 : 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 88 : if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1065 44 : (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT) ||
1066 16 : (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT))) {
1067 42 : 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 64 : 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 40 : if (q.query_secdesc.out.sd->dacl == NULL ||
1080 28 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1081 28 : 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 28 : 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 28 : if (q.query_secdesc.out.sd->dacl == NULL ||
1096 28 : q.query_secdesc.out.sd->dacl->num_aces != 2 ||
1097 28 : 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 28 : sd_orig->owner_sid) ||
1100 28 : 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 28 : 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 14 : if (q.query_secdesc.out.sd->dacl == NULL ||
1117 14 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1118 14 : 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 5 : 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 5 : 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 : NTSTATUS status;
1278 : 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 : int i, j;
1285 : union smb_fileinfo q;
1286 : union smb_setfileinfo set;
1287 4 : struct security_descriptor *sd, *sd2, *sd_orig=NULL;
1288 : const char *owner_sid;
1289 : 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 112 : 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 112 : 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 1792 : 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 : NTSTATUS status;
1512 : 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 : int i, j;
1519 : union smb_fileinfo q;
1520 : 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 : 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 112 : 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 112 : 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 1792 : 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 ownder doesn't affect SD flags.
1738 : *
1739 : * Do this by first changing ownder to world and then
1740 : * back to the original ownder. 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 : NTSTATUS status;
1788 : 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 : union smb_fileinfo q;
1795 : union smb_setfileinfo set;
1796 4 : struct security_descriptor *sd, *sd_orig=NULL;
1797 : 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 : /**
2143 : * SMB2 connect with explicit share
2144 : **/
2145 4 : static bool torture_smb2_con_share(struct torture_context *tctx,
2146 : const char *share,
2147 : struct smb2_tree **tree)
2148 : {
2149 : struct smbcli_options options;
2150 : NTSTATUS status;
2151 4 : const char *host = torture_setting_string(tctx, "host", NULL);
2152 :
2153 4 : lpcfg_smbcli_options(tctx->lp_ctx, &options);
2154 :
2155 4 : status = smb2_connect_ext(tctx,
2156 : host,
2157 : lpcfg_smb_ports(tctx->lp_ctx),
2158 : share,
2159 : lpcfg_resolve_context(tctx->lp_ctx),
2160 : samba_cmdline_get_creds(),
2161 : 0,
2162 : tree,
2163 : tctx->ev,
2164 : &options,
2165 : lpcfg_socket_options(tctx->lp_ctx),
2166 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
2167 : );
2168 4 : if (!NT_STATUS_IS_OK(status)) {
2169 0 : torture_comment(tctx, "Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
2170 : host, share, nt_errstr(status));
2171 0 : return false;
2172 : }
2173 4 : return true;
2174 : }
2175 :
2176 4 : static bool test_access_based(struct torture_context *tctx,
2177 : struct smb2_tree *tree)
2178 : {
2179 4 : struct smb2_tree *tree1 = NULL;
2180 : NTSTATUS status;
2181 : struct smb2_create io;
2182 4 : const char *fname = BASEDIR "\\testfile";
2183 4 : bool ret = true;
2184 : struct smb2_handle fhandle, dhandle;
2185 : union smb_fileinfo q;
2186 : union smb_setfileinfo set;
2187 4 : struct security_descriptor *sd, *sd_orig=NULL;
2188 : const char *owner_sid;
2189 4 : uint32_t flags = 0;
2190 : /*
2191 : * Can't test without SEC_STD_READ_CONTROL as we
2192 : * own the file and implicitly have SEC_STD_READ_CONTROL.
2193 : */
2194 4 : uint32_t access_masks[] = {
2195 : /* Full READ access. */
2196 : SEC_STD_READ_CONTROL|FILE_READ_DATA|
2197 : FILE_READ_ATTRIBUTES|FILE_READ_EA,
2198 :
2199 : /* Missing FILE_READ_EA. */
2200 : SEC_STD_READ_CONTROL|FILE_READ_DATA|
2201 : FILE_READ_ATTRIBUTES,
2202 :
2203 : /* Missing FILE_READ_ATTRIBUTES. */
2204 : SEC_STD_READ_CONTROL|FILE_READ_DATA|
2205 : FILE_READ_EA,
2206 :
2207 : /* Missing FILE_READ_DATA. */
2208 : SEC_STD_READ_CONTROL|
2209 : FILE_READ_ATTRIBUTES|FILE_READ_EA,
2210 : };
2211 : unsigned int i;
2212 : unsigned int count;
2213 : struct smb2_find f;
2214 : union smb_search_data *d;
2215 :
2216 4 : ZERO_STRUCT(fhandle);
2217 4 : ZERO_STRUCT(dhandle);
2218 :
2219 4 : if (!torture_smb2_con_share(tctx, "hideunread", &tree1)) {
2220 0 : torture_result(tctx, TORTURE_FAIL, "(%s) Unable to connect "
2221 : "to share 'hideunread'\n",
2222 : __location__);
2223 0 : ret = false;
2224 0 : goto done;
2225 : }
2226 :
2227 4 : flags = smb2cli_tcon_flags(tree1->smbXcli);
2228 :
2229 4 : smb2_util_unlink(tree1, fname);
2230 4 : smb2_deltree(tree1, BASEDIR);
2231 :
2232 4 : torture_comment(tctx, "TESTING ACCESS BASED ENUMERATION\n");
2233 :
2234 4 : if ((flags & SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM)==0) {
2235 0 : torture_result(tctx, TORTURE_FAIL, "(%s) No access enumeration "
2236 : "on share 'hideunread'\n",
2237 : __location__);
2238 0 : ret = false;
2239 0 : goto done;
2240 : }
2241 :
2242 4 : if (!smb2_util_setup_dir(tctx, tree1, BASEDIR)) {
2243 0 : torture_result(tctx, TORTURE_FAIL, "(%s) Unable to setup %s\n",
2244 : __location__, BASEDIR);
2245 0 : ret = false;
2246 0 : goto done;
2247 : }
2248 :
2249 : /* Get a handle to the BASEDIR directory. */
2250 4 : status = torture_smb2_testdir(tree1, BASEDIR, &dhandle);
2251 4 : CHECK_STATUS(status, NT_STATUS_OK);
2252 4 : smb2_util_close(tree1, dhandle);
2253 4 : ZERO_STRUCT(dhandle);
2254 :
2255 4 : ZERO_STRUCT(io);
2256 4 : io.level = RAW_OPEN_SMB2;
2257 4 : io.in.create_flags = 0;
2258 4 : io.in.desired_access = SEC_RIGHTS_FILE_ALL;
2259 4 : io.in.create_options = 0;
2260 4 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2261 4 : io.in.share_access = 0;
2262 4 : io.in.alloc_size = 0;
2263 4 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
2264 4 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
2265 4 : io.in.security_flags = 0;
2266 4 : io.in.fname = fname;
2267 :
2268 4 : status = smb2_create(tree1, tctx, &io);
2269 4 : CHECK_STATUS(status, NT_STATUS_OK);
2270 4 : fhandle = io.out.file.handle;
2271 :
2272 4 : torture_comment(tctx, "get the original sd\n");
2273 4 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2274 4 : q.query_secdesc.in.file.handle = fhandle;
2275 4 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2276 4 : status = smb2_getinfo_file(tree1, tctx, &q);
2277 4 : CHECK_STATUS(status, NT_STATUS_OK);
2278 4 : sd_orig = q.query_secdesc.out.sd;
2279 :
2280 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2281 :
2282 4 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
2283 :
2284 : /* Setup for the search. */
2285 4 : ZERO_STRUCT(f);
2286 4 : f.in.pattern = "*";
2287 4 : f.in.continue_flags = SMB2_CONTINUE_FLAG_REOPEN;
2288 4 : f.in.max_response_size = 0x1000;
2289 4 : f.in.level = SMB2_FIND_DIRECTORY_INFO;
2290 :
2291 20 : for (i = 0; i < ARRAY_SIZE(access_masks); i++) {
2292 :
2293 16 : sd = security_descriptor_dacl_create(tctx,
2294 : 0, NULL, NULL,
2295 : owner_sid,
2296 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2297 16 : access_masks[i]|SEC_STD_SYNCHRONIZE,
2298 : 0,
2299 : NULL);
2300 :
2301 16 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2302 16 : set.set_secdesc.in.file.handle = fhandle;
2303 16 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2304 16 : set.set_secdesc.in.sd = sd;
2305 16 : status = smb2_setinfo_file(tree1, &set);
2306 16 : CHECK_STATUS(status, NT_STATUS_OK);
2307 :
2308 : /* Now see if we can see the file in a directory listing. */
2309 :
2310 : /* Re-open dhandle. */
2311 16 : status = torture_smb2_testdir(tree1, BASEDIR, &dhandle);
2312 16 : CHECK_STATUS(status, NT_STATUS_OK);
2313 16 : f.in.file.handle = dhandle;
2314 :
2315 16 : count = 0;
2316 16 : d = NULL;
2317 16 : status = smb2_find_level(tree1, tree1, &f, &count, &d);
2318 16 : TALLOC_FREE(d);
2319 :
2320 16 : CHECK_STATUS(status, NT_STATUS_OK);
2321 :
2322 16 : smb2_util_close(tree1, dhandle);
2323 16 : ZERO_STRUCT(dhandle);
2324 :
2325 16 : if (i == 0) {
2326 : /* We should see the first sd. */
2327 4 : if (count != 3) {
2328 0 : torture_result(tctx, TORTURE_FAIL,
2329 : "(%s) Normal SD - Unable "
2330 : "to see file %s\n",
2331 : __location__,
2332 : BASEDIR);
2333 0 : ret = false;
2334 0 : goto done;
2335 : }
2336 : } else {
2337 : /* But no others. */
2338 12 : if (count != 2) {
2339 0 : torture_result(tctx, TORTURE_FAIL,
2340 : "(%s) SD 0x%x - can "
2341 : "see file %s\n",
2342 : __location__,
2343 : access_masks[i],
2344 : BASEDIR);
2345 0 : ret = false;
2346 0 : goto done;
2347 : }
2348 : }
2349 : }
2350 :
2351 4 : done:
2352 :
2353 4 : if (tree1) {
2354 4 : smb2_util_close(tree1, fhandle);
2355 4 : smb2_util_close(tree1, dhandle);
2356 4 : smb2_util_unlink(tree1, fname);
2357 4 : smb2_deltree(tree1, BASEDIR);
2358 4 : smb2_tdis(tree1);
2359 4 : smb2_logoff(tree1->session);
2360 : }
2361 4 : smb2_tdis(tree);
2362 4 : smb2_logoff(tree->session);
2363 4 : return ret;
2364 : }
2365 :
2366 : /*
2367 : * test Owner Rights, S-1-3-4
2368 : */
2369 4 : static bool test_owner_rights(struct torture_context *tctx,
2370 : struct smb2_tree *tree)
2371 : {
2372 4 : const char *fname = BASEDIR "\\owner_right.txt";
2373 : struct smb2_create cr;
2374 4 : struct smb2_handle handle = {{0}};
2375 : union smb_fileinfo gi;
2376 : union smb_setfileinfo si;
2377 4 : struct security_descriptor *sd_orig = NULL;
2378 4 : struct security_descriptor *sd = NULL;
2379 4 : const char *owner_sid = NULL;
2380 : NTSTATUS mxac_status;
2381 : NTSTATUS status;
2382 4 : bool ret = true;
2383 :
2384 4 : smb2_deltree(tree, BASEDIR);
2385 :
2386 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2387 4 : torture_assert_goto(tctx, ret, ret, done,
2388 : "smb2_util_setup_dir failed\n");
2389 :
2390 4 : torture_comment(tctx, "TESTING OWNER RIGHTS\n");
2391 :
2392 4 : cr = (struct smb2_create) {
2393 : .in.desired_access = SEC_STD_READ_CONTROL |
2394 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2395 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2396 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2397 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2398 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2399 : .in.fname = fname,
2400 : };
2401 :
2402 4 : status = smb2_create(tree, tctx, &cr);
2403 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2404 : "smb2_create failed\n");
2405 4 : handle = cr.out.file.handle;
2406 :
2407 4 : torture_comment(tctx, "get the original sd\n");
2408 :
2409 4 : gi = (union smb_fileinfo) {
2410 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2411 : .query_secdesc.in.file.handle = handle,
2412 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2413 : };
2414 :
2415 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2416 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2417 : "smb2_getinfo_file failed\n");
2418 :
2419 4 : sd_orig = gi.query_secdesc.out.sd;
2420 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2421 :
2422 : /*
2423 : * Add a 2 element ACL
2424 : * SEC_RIGHTS_FILE_READ for the owner,
2425 : * SEC_FILE_WRITE_DATA for SID_OWNER_RIGHTS.
2426 : *
2427 : * Proves that the owner and SID_OWNER_RIGHTS
2428 : * ACE entries are additive.
2429 : */
2430 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2431 : owner_sid,
2432 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2433 : SEC_RIGHTS_FILE_READ,
2434 : 0,
2435 : SID_OWNER_RIGHTS,
2436 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2437 : SEC_FILE_WRITE_DATA,
2438 : 0,
2439 : NULL);
2440 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2441 : "SD create failed\n");
2442 :
2443 4 : si = (union smb_setfileinfo) {
2444 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2445 : .set_secdesc.in.file.handle = handle,
2446 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2447 : .set_secdesc.in.sd = sd,
2448 : };
2449 :
2450 4 : status = smb2_setinfo_file(tree, &si);
2451 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2452 : "smb2_setinfo_file failed\n");
2453 :
2454 4 : status = smb2_util_close(tree, handle);
2455 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2456 : "smb2_util_close failed\n");
2457 4 : ZERO_STRUCT(handle);
2458 :
2459 4 : cr = (struct smb2_create) {
2460 : .in.desired_access = SEC_STD_READ_CONTROL,
2461 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2462 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2463 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2464 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2465 : .in.query_maximal_access = true,
2466 : .in.fname = fname,
2467 : };
2468 :
2469 4 : status = smb2_create(tree, tctx, &cr);
2470 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2471 : "smb2_setinfo_file failed\n");
2472 4 : handle = cr.out.file.handle;
2473 :
2474 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2475 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2476 : "smb2_setinfo_file failed\n");
2477 :
2478 : /*
2479 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2480 : * do. Mask it out so the test passes against Samba and Windows.
2481 : */
2482 4 : torture_assert_int_equal_goto(tctx,
2483 : cr.out.maximal_access & ~SEC_STD_DELETE,
2484 : SEC_RIGHTS_FILE_READ |
2485 : SEC_FILE_WRITE_DATA,
2486 : ret, done,
2487 : "Wrong maximum access\n");
2488 :
2489 4 : status = smb2_util_close(tree, handle);
2490 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2491 : "smb2_util_close failed\n");
2492 4 : ZERO_STRUCT(handle);
2493 :
2494 4 : done:
2495 4 : if (!smb2_util_handle_empty(handle)) {
2496 0 : smb2_util_close(tree, handle);
2497 : }
2498 4 : smb2_deltree(tree, BASEDIR);
2499 4 : return ret;
2500 : }
2501 :
2502 : /*
2503 : * test Owner Rights with a leading DENY ACE, S-1-3-4
2504 : */
2505 4 : static bool test_owner_rights_deny(struct torture_context *tctx,
2506 : struct smb2_tree *tree)
2507 : {
2508 4 : const char *fname = BASEDIR "\\owner_right_deny.txt";
2509 : struct smb2_create cr;
2510 4 : struct smb2_handle handle = {{0}};
2511 : union smb_fileinfo gi;
2512 : union smb_setfileinfo si;
2513 4 : struct security_descriptor *sd_orig = NULL;
2514 4 : struct security_descriptor *sd = NULL;
2515 4 : const char *owner_sid = NULL;
2516 : NTSTATUS mxac_status;
2517 : NTSTATUS status;
2518 4 : bool ret = true;
2519 :
2520 4 : smb2_deltree(tree, BASEDIR);
2521 :
2522 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2523 4 : torture_assert_goto(tctx, ret, ret, done,
2524 : "smb2_util_setup_dir failed\n");
2525 :
2526 4 : torture_comment(tctx, "TESTING OWNER RIGHTS DENY\n");
2527 :
2528 4 : cr = (struct smb2_create) {
2529 : .in.desired_access = SEC_STD_READ_CONTROL |
2530 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2531 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2532 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2533 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2534 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2535 : .in.fname = fname,
2536 : };
2537 :
2538 4 : status = smb2_create(tree, tctx, &cr);
2539 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2540 : "smb2_create failed\n");
2541 4 : handle = cr.out.file.handle;
2542 :
2543 4 : torture_comment(tctx, "get the original sd\n");
2544 :
2545 4 : gi = (union smb_fileinfo) {
2546 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2547 : .query_secdesc.in.file.handle = handle,
2548 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2549 : };
2550 :
2551 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2552 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2553 : "smb2_getinfo_file failed\n");
2554 :
2555 4 : sd_orig = gi.query_secdesc.out.sd;
2556 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2557 :
2558 : /*
2559 : * Add a 2 element ACL
2560 : * DENY SEC_FILE_DATA_READ for SID_OWNER_RIGHTS
2561 : * SEC_FILE_READ_DATA for the owner.
2562 : *
2563 : * Proves that the owner and SID_OWNER_RIGHTS
2564 : * ACE entries are additive.
2565 : */
2566 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2567 : SID_OWNER_RIGHTS,
2568 : SEC_ACE_TYPE_ACCESS_DENIED,
2569 : SEC_FILE_READ_DATA,
2570 : 0,
2571 : owner_sid,
2572 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2573 : SEC_RIGHTS_FILE_READ,
2574 : 0,
2575 : NULL);
2576 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2577 : "SD create failed\n");
2578 :
2579 4 : si = (union smb_setfileinfo) {
2580 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2581 : .set_secdesc.in.file.handle = handle,
2582 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2583 : .set_secdesc.in.sd = sd,
2584 : };
2585 :
2586 4 : status = smb2_setinfo_file(tree, &si);
2587 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2588 : "smb2_setinfo_file failed\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 : cr = (struct smb2_create) {
2596 : .in.desired_access = SEC_STD_READ_CONTROL,
2597 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2598 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2599 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2600 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2601 : .in.query_maximal_access = true,
2602 : .in.fname = fname,
2603 : };
2604 :
2605 4 : status = smb2_create(tree, tctx, &cr);
2606 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2607 : "smb2_setinfo_file failed\n");
2608 4 : handle = cr.out.file.handle;
2609 :
2610 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2611 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2612 : "smb2_setinfo_file failed\n");
2613 :
2614 : /*
2615 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2616 : * do. Mask it out so the test passes against Samba and Windows.
2617 : */
2618 4 : torture_assert_int_equal_goto(tctx,
2619 : cr.out.maximal_access & ~SEC_STD_DELETE,
2620 : SEC_RIGHTS_FILE_READ & ~SEC_FILE_READ_DATA,
2621 : ret, done,
2622 : "Wrong maximum access\n");
2623 :
2624 4 : status = smb2_util_close(tree, handle);
2625 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2626 : "smb2_util_close failed\n");
2627 4 : ZERO_STRUCT(handle);
2628 :
2629 4 : done:
2630 4 : if (!smb2_util_handle_empty(handle)) {
2631 0 : smb2_util_close(tree, handle);
2632 : }
2633 4 : smb2_deltree(tree, BASEDIR);
2634 4 : return ret;
2635 : }
2636 :
2637 : /*
2638 : * test Owner Rights with a trailing DENY ACE, S-1-3-4
2639 : */
2640 4 : static bool test_owner_rights_deny1(struct torture_context *tctx,
2641 : struct smb2_tree *tree)
2642 : {
2643 4 : const char *fname = BASEDIR "\\owner_right_deny1.txt";
2644 : struct smb2_create cr;
2645 4 : struct smb2_handle handle = {{0}};
2646 : union smb_fileinfo gi;
2647 : union smb_setfileinfo si;
2648 4 : struct security_descriptor *sd_orig = NULL;
2649 4 : struct security_descriptor *sd = NULL;
2650 4 : const char *owner_sid = NULL;
2651 : NTSTATUS mxac_status;
2652 : NTSTATUS status;
2653 4 : bool ret = true;
2654 :
2655 4 : smb2_deltree(tree, BASEDIR);
2656 :
2657 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2658 4 : torture_assert_goto(tctx, ret, ret, done,
2659 : "smb2_util_setup_dir failed\n");
2660 :
2661 4 : torture_comment(tctx, "TESTING OWNER RIGHTS DENY1\n");
2662 :
2663 4 : cr = (struct smb2_create) {
2664 : .in.desired_access = SEC_STD_READ_CONTROL |
2665 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2666 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2667 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2668 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2669 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2670 : .in.fname = fname,
2671 : };
2672 :
2673 4 : status = smb2_create(tree, tctx, &cr);
2674 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2675 : "smb2_create failed\n");
2676 4 : handle = cr.out.file.handle;
2677 :
2678 4 : torture_comment(tctx, "get the original sd\n");
2679 :
2680 4 : gi = (union smb_fileinfo) {
2681 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2682 : .query_secdesc.in.file.handle = handle,
2683 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2684 : };
2685 :
2686 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2687 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2688 : "smb2_getinfo_file failed\n");
2689 :
2690 4 : sd_orig = gi.query_secdesc.out.sd;
2691 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2692 :
2693 : /*
2694 : * Add a 3 element ACL
2695 : *
2696 : * SEC_RIGHTS_FILE_READ allow for owner.
2697 : * SEC_FILE_WRITE_DATA allow for SID-OWNER-RIGHTS.
2698 : * SEC_FILE_WRITE_DATA|SEC_FILE_READ_DATA) deny for SID-OWNER-RIGHTS.
2699 : *
2700 : * Shows on Windows that trailing DENY entries don't
2701 : * override granted permissions in max access calculations.
2702 : */
2703 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2704 : owner_sid,
2705 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2706 : SEC_RIGHTS_FILE_READ,
2707 : 0,
2708 : SID_OWNER_RIGHTS,
2709 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2710 : SEC_FILE_WRITE_DATA,
2711 : 0,
2712 : SID_OWNER_RIGHTS,
2713 : SEC_ACE_TYPE_ACCESS_DENIED,
2714 : (SEC_FILE_WRITE_DATA|
2715 : SEC_FILE_READ_DATA),
2716 : 0,
2717 : NULL);
2718 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2719 : "SD create failed\n");
2720 :
2721 4 : si = (union smb_setfileinfo) {
2722 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2723 : .set_secdesc.in.file.handle = handle,
2724 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2725 : .set_secdesc.in.sd = sd,
2726 : };
2727 :
2728 4 : status = smb2_setinfo_file(tree, &si);
2729 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2730 : "smb2_setinfo_file failed\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 : cr = (struct smb2_create) {
2738 : .in.desired_access = SEC_STD_READ_CONTROL,
2739 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2740 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2741 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2742 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2743 : .in.query_maximal_access = true,
2744 : .in.fname = fname,
2745 : };
2746 :
2747 4 : status = smb2_create(tree, tctx, &cr);
2748 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2749 : "smb2_setinfo_file failed\n");
2750 4 : handle = cr.out.file.handle;
2751 :
2752 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2753 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2754 : "smb2_setinfo_file failed\n");
2755 :
2756 : /*
2757 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2758 : * do. Mask it out so the test passes against Samba and Windows.
2759 : */
2760 4 : torture_assert_int_equal_goto(tctx,
2761 : cr.out.maximal_access & ~SEC_STD_DELETE,
2762 : SEC_RIGHTS_FILE_READ | SEC_FILE_WRITE_DATA,
2763 : ret, done,
2764 : "Wrong maximum access\n");
2765 :
2766 4 : status = smb2_util_close(tree, handle);
2767 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2768 : "smb2_util_close failed\n");
2769 4 : ZERO_STRUCT(handle);
2770 :
2771 4 : done:
2772 4 : if (!smb2_util_handle_empty(handle)) {
2773 0 : smb2_util_close(tree, handle);
2774 : }
2775 4 : smb2_deltree(tree, BASEDIR);
2776 4 : return ret;
2777 : }
2778 :
2779 : /*
2780 : * test that shows that a DENY ACE doesn't remove rights granted
2781 : * by a previous ALLOW ACE.
2782 : */
2783 4 : static bool test_deny1(struct torture_context *tctx,
2784 : struct smb2_tree *tree)
2785 : {
2786 4 : const char *fname = BASEDIR "\\test_deny1.txt";
2787 : struct smb2_create cr;
2788 4 : struct smb2_handle handle = {{0}};
2789 : union smb_fileinfo gi;
2790 : union smb_setfileinfo si;
2791 4 : struct security_descriptor *sd_orig = NULL;
2792 4 : struct security_descriptor *sd = NULL;
2793 4 : const char *owner_sid = NULL;
2794 : NTSTATUS mxac_status;
2795 : NTSTATUS status;
2796 4 : bool ret = true;
2797 :
2798 4 : smb2_deltree(tree, BASEDIR);
2799 :
2800 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2801 4 : torture_assert_goto(tctx, ret, ret, done,
2802 : "smb2_util_setup_dir failed\n");
2803 :
2804 4 : cr = (struct smb2_create) {
2805 : .in.desired_access = SEC_STD_READ_CONTROL |
2806 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2807 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2808 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2809 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2810 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2811 : .in.fname = fname,
2812 : };
2813 :
2814 4 : status = smb2_create(tree, tctx, &cr);
2815 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2816 : "smb2_create failed\n");
2817 4 : handle = cr.out.file.handle;
2818 :
2819 4 : torture_comment(tctx, "get the original sd\n");
2820 :
2821 4 : gi = (union smb_fileinfo) {
2822 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2823 : .query_secdesc.in.file.handle = handle,
2824 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2825 : };
2826 :
2827 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2828 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2829 : "smb2_getinfo_file failed\n");
2830 :
2831 4 : sd_orig = gi.query_secdesc.out.sd;
2832 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2833 :
2834 : /*
2835 : * Add a 2 element ACL
2836 : *
2837 : * SEC_RIGHTS_FILE_READ|SEC_FILE_WRITE_DATA allow for owner.
2838 : * SEC_FILE_WRITE_DATA deny for owner
2839 : *
2840 : * Shows on Windows that trailing DENY entries don't
2841 : * override granted permissions.
2842 : */
2843 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2844 : owner_sid,
2845 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2846 : SEC_RIGHTS_FILE_READ|SEC_FILE_WRITE_DATA,
2847 : 0,
2848 : owner_sid,
2849 : SEC_ACE_TYPE_ACCESS_DENIED,
2850 : SEC_FILE_WRITE_DATA,
2851 : 0,
2852 : NULL);
2853 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2854 : "SD create failed\n");
2855 :
2856 4 : si = (union smb_setfileinfo) {
2857 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2858 : .set_secdesc.in.file.handle = handle,
2859 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2860 : .set_secdesc.in.sd = sd,
2861 : };
2862 :
2863 4 : status = smb2_setinfo_file(tree, &si);
2864 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2865 : "smb2_setinfo_file failed\n");
2866 :
2867 4 : status = smb2_util_close(tree, handle);
2868 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2869 : "smb2_util_close failed\n");
2870 4 : ZERO_STRUCT(handle);
2871 :
2872 4 : cr = (struct smb2_create) {
2873 : .in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_WRITE_DATA,
2874 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2875 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2876 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2877 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2878 : .in.query_maximal_access = true,
2879 : .in.fname = fname,
2880 : };
2881 :
2882 4 : status = smb2_create(tree, tctx, &cr);
2883 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2884 : "smb2_create failed\n");
2885 4 : handle = cr.out.file.handle;
2886 :
2887 4 : mxac_status = NT_STATUS(cr.out.maximal_access_status);
2888 4 : torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
2889 : "Wrong maximum access status\n");
2890 :
2891 : /*
2892 : * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2893 : * do. Mask it out so the test passes against Samba and Windows.
2894 : * SEC_STD_WRITE_DAC comes from being the owner.
2895 : */
2896 4 : torture_assert_int_equal_goto(tctx,
2897 : cr.out.maximal_access & ~SEC_STD_DELETE,
2898 : SEC_RIGHTS_FILE_READ |
2899 : SEC_FILE_WRITE_DATA |
2900 : SEC_STD_WRITE_DAC,
2901 : ret, done,
2902 : "Wrong maximum access\n");
2903 :
2904 4 : status = smb2_util_close(tree, handle);
2905 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2906 : "smb2_util_close failed\n");
2907 4 : ZERO_STRUCT(handle);
2908 :
2909 4 : done:
2910 4 : if (!smb2_util_handle_empty(handle)) {
2911 0 : smb2_util_close(tree, handle);
2912 : }
2913 4 : smb2_deltree(tree, BASEDIR);
2914 4 : return ret;
2915 : }
2916 :
2917 : /*
2918 : * test SEC_FLAG_MAXIMUM_ALLOWED with not-granted access
2919 : *
2920 : * When access_mask contains SEC_FLAG_MAXIMUM_ALLOWED, the server must still
2921 : * proces other bits from access_mask. Eg if access_mask contains a right that
2922 : * the requester doesn't have, the function must validate that against the
2923 : * effective permissions.
2924 : */
2925 4 : static bool test_mxac_not_granted(struct torture_context *tctx,
2926 : struct smb2_tree *tree)
2927 : {
2928 4 : const char *fname = BASEDIR "\\test_mxac_not_granted.txt";
2929 : struct smb2_create cr;
2930 4 : struct smb2_handle handle = {{0}};
2931 : union smb_fileinfo gi;
2932 : union smb_setfileinfo si;
2933 4 : struct security_descriptor *sd_orig = NULL;
2934 4 : struct security_descriptor *sd = NULL;
2935 4 : const char *owner_sid = NULL;
2936 : NTSTATUS status;
2937 4 : bool ret = true;
2938 :
2939 4 : smb2_deltree(tree, BASEDIR);
2940 :
2941 4 : ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
2942 4 : torture_assert_goto(tctx, ret, ret, done,
2943 : "smb2_util_setup_dir failed\n");
2944 :
2945 4 : torture_comment(tctx, "TESTING OWNER RIGHTS DENY\n");
2946 :
2947 4 : cr = (struct smb2_create) {
2948 : .in.desired_access = SEC_STD_READ_CONTROL |
2949 : SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
2950 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2951 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2952 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2953 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
2954 : .in.fname = fname,
2955 : };
2956 :
2957 4 : status = smb2_create(tree, tctx, &cr);
2958 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2959 : "smb2_create failed\n");
2960 4 : handle = cr.out.file.handle;
2961 :
2962 4 : torture_comment(tctx, "get the original sd\n");
2963 :
2964 4 : gi = (union smb_fileinfo) {
2965 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
2966 : .query_secdesc.in.file.handle = handle,
2967 : .query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
2968 : };
2969 :
2970 4 : status = smb2_getinfo_file(tree, tctx, &gi);
2971 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2972 : "smb2_getinfo_file failed\n");
2973 :
2974 4 : sd_orig = gi.query_secdesc.out.sd;
2975 4 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2976 :
2977 4 : sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
2978 : owner_sid,
2979 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2980 : SEC_FILE_READ_DATA,
2981 : 0,
2982 : NULL);
2983 4 : torture_assert_not_null_goto(tctx, sd, ret, done,
2984 : "SD create failed\n");
2985 :
2986 4 : si = (union smb_setfileinfo) {
2987 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
2988 : .set_secdesc.in.file.handle = handle,
2989 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
2990 : .set_secdesc.in.sd = sd,
2991 : };
2992 :
2993 4 : status = smb2_setinfo_file(tree, &si);
2994 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2995 : "smb2_setinfo_file failed\n");
2996 :
2997 4 : status = smb2_util_close(tree, handle);
2998 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2999 : "smb2_util_close failed\n");
3000 4 : ZERO_STRUCT(handle);
3001 :
3002 4 : cr = (struct smb2_create) {
3003 : .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED |
3004 : SEC_FILE_WRITE_DATA,
3005 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3006 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3007 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
3008 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3009 : .in.fname = fname,
3010 : };
3011 :
3012 4 : status = smb2_create(tree, tctx, &cr);
3013 4 : torture_assert_ntstatus_equal_goto(tctx, status,
3014 : NT_STATUS_ACCESS_DENIED,
3015 : ret, done,
3016 : "Wrong smb2_create result\n");
3017 :
3018 4 : done:
3019 4 : if (!smb2_util_handle_empty(handle)) {
3020 0 : smb2_util_close(tree, handle);
3021 : }
3022 4 : smb2_deltree(tree, BASEDIR);
3023 4 : return ret;
3024 : }
3025 :
3026 : /*
3027 : basic testing of SMB2 ACLs
3028 : */
3029 2355 : struct torture_suite *torture_smb2_acls_init(TALLOC_CTX *ctx)
3030 : {
3031 2355 : struct torture_suite *suite = torture_suite_create(ctx, "acls");
3032 :
3033 2355 : torture_suite_add_1smb2_test(suite, "CREATOR", test_creator_sid);
3034 2355 : torture_suite_add_1smb2_test(suite, "GENERIC", test_generic_bits);
3035 2355 : torture_suite_add_1smb2_test(suite, "OWNER", test_owner_bits);
3036 2355 : torture_suite_add_1smb2_test(suite, "INHERITANCE", test_inheritance);
3037 2355 : torture_suite_add_1smb2_test(suite, "INHERITFLAGS", test_inheritance_flags);
3038 2355 : torture_suite_add_1smb2_test(suite, "SDFLAGSVSCHOWN", test_sd_flags_vs_chown);
3039 2355 : torture_suite_add_1smb2_test(suite, "DYNAMIC", test_inheritance_dynamic);
3040 : #if 0
3041 : /* XXX This test does not work against XP or Vista. */
3042 : torture_suite_add_1smb2_test(suite, "GETSET", test_sd_get_set);
3043 : #endif
3044 2355 : torture_suite_add_1smb2_test(suite, "ACCESSBASED", test_access_based);
3045 2355 : torture_suite_add_1smb2_test(suite, "OWNER-RIGHTS", test_owner_rights);
3046 2355 : torture_suite_add_1smb2_test(suite, "OWNER-RIGHTS-DENY",
3047 : test_owner_rights_deny);
3048 2355 : torture_suite_add_1smb2_test(suite, "OWNER-RIGHTS-DENY1",
3049 : test_owner_rights_deny1);
3050 2355 : torture_suite_add_1smb2_test(suite, "DENY1",
3051 : test_deny1);
3052 2355 : torture_suite_add_1smb2_test(suite, "MXAC-NOT-GRANTED",
3053 : test_mxac_not_granted);
3054 :
3055 2355 : suite->description = talloc_strdup(suite, "SMB2-ACLS tests");
3056 :
3057 2355 : return suite;
3058 : }
3059 :
3060 2 : static bool test_acls_non_canonical_flags(struct torture_context *tctx,
3061 : struct smb2_tree *tree)
3062 : {
3063 2 : const char *fname = BASEDIR "\\test_acls_non_canonical_flags.txt";
3064 : struct smb2_create cr;
3065 2 : struct smb2_handle testdirh = {{0}};
3066 2 : struct smb2_handle handle = {{0}};
3067 : union smb_fileinfo gi;
3068 : union smb_setfileinfo si;
3069 2 : struct security_descriptor *sd_orig = NULL;
3070 2 : struct security_descriptor *sd = NULL;
3071 : NTSTATUS status;
3072 2 : bool ret = true;
3073 :
3074 2 : smb2_deltree(tree, BASEDIR);
3075 :
3076 2 : status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
3077 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3078 : "torture_smb2_testdir failed\n");
3079 :
3080 2 : sd = security_descriptor_dacl_create(tctx,
3081 : SEC_DESC_DACL_AUTO_INHERITED
3082 : | SEC_DESC_DACL_AUTO_INHERIT_REQ,
3083 : NULL,
3084 : NULL,
3085 : SID_WORLD,
3086 : SEC_ACE_TYPE_ACCESS_ALLOWED,
3087 : SEC_RIGHTS_DIR_ALL,
3088 : SEC_ACE_FLAG_OBJECT_INHERIT
3089 : | SEC_ACE_FLAG_CONTAINER_INHERIT,
3090 : NULL);
3091 2 : torture_assert_not_null_goto(tctx, sd, ret, done,
3092 : "SD create failed\n");
3093 :
3094 2 : si = (union smb_setfileinfo) {
3095 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
3096 : .set_secdesc.in.file.handle = testdirh,
3097 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
3098 : .set_secdesc.in.sd = sd,
3099 : };
3100 :
3101 2 : status = smb2_setinfo_file(tree, &si);
3102 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3103 : "smb2_setinfo_file failed\n");
3104 :
3105 2 : gi = (union smb_fileinfo) {
3106 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
3107 : .query_secdesc.in.file.handle = testdirh,
3108 : .query_secdesc.in.secinfo_flags = SECINFO_DACL,
3109 : };
3110 :
3111 2 : status = smb2_getinfo_file(tree, tctx, &gi);
3112 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3113 : "smb2_getinfo_file failed\n");
3114 :
3115 2 : cr = (struct smb2_create) {
3116 : .in.desired_access = SEC_STD_READ_CONTROL |
3117 : SEC_STD_WRITE_DAC,
3118 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3119 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3120 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
3121 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3122 : .in.fname = fname,
3123 : };
3124 :
3125 2 : status = smb2_create(tree, tctx, &cr);
3126 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3127 : "smb2_create failed\n");
3128 2 : handle = cr.out.file.handle;
3129 :
3130 2 : torture_comment(tctx, "get the original sd\n");
3131 :
3132 2 : gi = (union smb_fileinfo) {
3133 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
3134 : .query_secdesc.in.file.handle = handle,
3135 : .query_secdesc.in.secinfo_flags = SECINFO_DACL,
3136 : };
3137 :
3138 2 : status = smb2_getinfo_file(tree, tctx, &gi);
3139 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3140 : "smb2_getinfo_file failed\n");
3141 :
3142 2 : sd_orig = gi.query_secdesc.out.sd;
3143 :
3144 2 : torture_assert_goto(tctx, sd_orig->type & SEC_DESC_DACL_AUTO_INHERITED,
3145 : ret, done, "Missing SEC_DESC_DACL_AUTO_INHERITED\n");
3146 :
3147 : /*
3148 : * SD with SEC_DESC_DACL_AUTO_INHERITED but without
3149 : * SEC_DESC_DACL_AUTO_INHERITED_REQ, so the resulting SD should not have
3150 : * SEC_DESC_DACL_AUTO_INHERITED on a Windows box.
3151 : *
3152 : * But as we're testing against a share with
3153 : *
3154 : * "acl flag inherited canonicalization = no"
3155 : *
3156 : * the resulting SD should have acl flag inherited canonicalization set.
3157 : */
3158 2 : sd = security_descriptor_dacl_create(tctx,
3159 : SEC_DESC_DACL_AUTO_INHERITED,
3160 : NULL,
3161 : NULL,
3162 : SID_WORLD,
3163 : SEC_ACE_TYPE_ACCESS_ALLOWED,
3164 : SEC_FILE_ALL,
3165 : 0,
3166 : NULL);
3167 2 : torture_assert_not_null_goto(tctx, sd, ret, done,
3168 : "SD create failed\n");
3169 :
3170 2 : si = (union smb_setfileinfo) {
3171 : .set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
3172 : .set_secdesc.in.file.handle = handle,
3173 : .set_secdesc.in.secinfo_flags = SECINFO_DACL,
3174 : .set_secdesc.in.sd = sd,
3175 : };
3176 :
3177 2 : status = smb2_setinfo_file(tree, &si);
3178 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3179 : "smb2_setinfo_file failed\n");
3180 :
3181 2 : status = smb2_util_close(tree, handle);
3182 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3183 : "smb2_util_close failed\n");
3184 2 : ZERO_STRUCT(handle);
3185 :
3186 2 : cr = (struct smb2_create) {
3187 : .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED ,
3188 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3189 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3190 : .in.create_disposition = NTCREATEX_DISP_OPEN,
3191 : .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
3192 : .in.fname = fname,
3193 : };
3194 :
3195 2 : status = smb2_create(tree, tctx, &cr);
3196 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3197 : "smb2_create failed\n");
3198 2 : handle = cr.out.file.handle;
3199 :
3200 2 : gi = (union smb_fileinfo) {
3201 : .query_secdesc.level = RAW_FILEINFO_SEC_DESC,
3202 : .query_secdesc.in.file.handle = handle,
3203 : .query_secdesc.in.secinfo_flags = SECINFO_DACL,
3204 : };
3205 :
3206 2 : status = smb2_getinfo_file(tree, tctx, &gi);
3207 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3208 : "smb2_getinfo_file failed\n");
3209 :
3210 2 : sd_orig = gi.query_secdesc.out.sd;
3211 2 : torture_assert_goto(tctx, sd_orig->type & SEC_DESC_DACL_AUTO_INHERITED,
3212 : ret, done, "Missing SEC_DESC_DACL_AUTO_INHERITED\n");
3213 :
3214 4 : done:
3215 2 : if (!smb2_util_handle_empty(handle)) {
3216 2 : smb2_util_close(tree, testdirh);
3217 : }
3218 2 : if (!smb2_util_handle_empty(handle)) {
3219 2 : smb2_util_close(tree, handle);
3220 : }
3221 2 : smb2_deltree(tree, BASEDIR);
3222 2 : return ret;
3223 : }
3224 :
3225 2355 : struct torture_suite *torture_smb2_acls_non_canonical_init(TALLOC_CTX *ctx)
3226 : {
3227 2355 : struct torture_suite *suite = torture_suite_create(ctx, "acls_non_canonical");
3228 :
3229 2355 : torture_suite_add_1smb2_test(suite, "flags", test_acls_non_canonical_flags);
3230 2355 : return suite;
3231 : }
|