Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : test security descriptor operations
5 :
6 : Copyright (C) Andrew Tridgell 2004
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 "torture/torture.h"
24 : #include "libcli/raw/libcliraw.h"
25 : #include "libcli/libcli.h"
26 : #include "librpc/gen_ndr/lsa.h"
27 : #include "libcli/smb2/smb2.h"
28 : #include "libcli/util/clilsa.h"
29 : #include "libcli/security/security.h"
30 : #include "torture/util.h"
31 : #include "librpc/gen_ndr/ndr_security.h"
32 : #include "torture/raw/proto.h"
33 :
34 : #define BASEDIR "\\testsd"
35 :
36 : #define CHECK_STATUS(status, correct) do { \
37 : if (!NT_STATUS_EQUAL(status, correct)) { \
38 : ret = false; \
39 : torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
40 : __location__, nt_errstr(status), nt_errstr(correct)); \
41 : goto done; \
42 : }} while (0)
43 :
44 : #define FAIL_UNLESS(__cond) \
45 : do { \
46 : if (__cond) {} else { \
47 : ret = false; \
48 : torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \
49 : __location__, #__cond); \
50 : goto done; \
51 : } \
52 : } while(0)
53 :
54 : #define CHECK_SECURITY_DESCRIPTOR(_sd1, _sd2) do { \
55 : if (!security_descriptor_equal(_sd1, _sd2)) { \
56 : torture_warning(tctx, "%s: security descriptors don't match!\n", __location__); \
57 : torture_warning(tctx, "got:\n"); \
58 : NDR_PRINT_DEBUG(security_descriptor, _sd1); \
59 : torture_warning(tctx, "expected:\n"); \
60 : NDR_PRINT_DEBUG(security_descriptor, _sd2); \
61 : ret = false; \
62 : } \
63 : } while (0)
64 :
65 : /*
66 : * Helper function to verify a security descriptor, by querying
67 : * and comparing against the passed in sd.
68 : * Copied to smb2_util_verify_sd() for SMB2.
69 : */
70 7 : static bool verify_sd(TALLOC_CTX *tctx, struct smbcli_state *cli,
71 : int fnum, struct security_descriptor *sd)
72 : {
73 : NTSTATUS status;
74 7 : bool ret = true;
75 7 : union smb_fileinfo q = {};
76 :
77 7 : if (sd) {
78 7 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
79 7 : q.query_secdesc.in.file.fnum = fnum;
80 7 : q.query_secdesc.in.secinfo_flags =
81 : SECINFO_OWNER |
82 : SECINFO_GROUP |
83 : SECINFO_DACL;
84 7 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
85 7 : CHECK_STATUS(status, NT_STATUS_OK);
86 :
87 : /* More work is needed if we're going to check this bit. */
88 7 : sd->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
89 :
90 9 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
91 : }
92 :
93 12 : done:
94 7 : return ret;
95 : }
96 :
97 : /*
98 : * Helper function to verify attributes, by querying
99 : * and comparing against the passed attrib.
100 : * Copied to smb2_util_verify_attrib() for SMB2.
101 : */
102 3 : static bool verify_attrib(TALLOC_CTX *tctx, struct smbcli_state *cli,
103 : int fnum, uint32_t attrib)
104 : {
105 : NTSTATUS status;
106 3 : bool ret = true;
107 3 : union smb_fileinfo q2 = {};
108 :
109 3 : if (attrib) {
110 3 : q2.standard.level = RAW_FILEINFO_STANDARD;
111 3 : q2.standard.in.file.fnum = fnum;
112 3 : status = smb_raw_fileinfo(cli->tree, tctx, &q2);
113 3 : CHECK_STATUS(status, NT_STATUS_OK);
114 :
115 3 : q2.standard.out.attrib &= ~FILE_ATTRIBUTE_ARCHIVE;
116 :
117 3 : if (q2.standard.out.attrib != attrib) {
118 1 : torture_warning(tctx, "%s: attributes don't match! "
119 : "got %x, expected %x\n", __location__,
120 1 : (uint32_t)q2.standard.out.attrib,
121 : (uint32_t)attrib);
122 1 : ret = false;
123 : }
124 : }
125 :
126 5 : done:
127 3 : return ret;
128 : }
129 :
130 : /**
131 : * Test setting and removing a DACL.
132 : * Test copied to torture_smb2_setinfo() for SMB2.
133 : */
134 1 : static bool test_sd(struct torture_context *tctx, struct smbcli_state *cli)
135 : {
136 : NTSTATUS status;
137 : union smb_open io;
138 1 : const char *fname = BASEDIR "\\sd.txt";
139 1 : bool ret = true;
140 1 : int fnum = -1;
141 : union smb_fileinfo q;
142 : union smb_setfileinfo set;
143 : struct security_ace ace;
144 : struct security_descriptor *sd;
145 : struct dom_sid *test_sid;
146 :
147 1 : if (!torture_setup_dir(cli, BASEDIR))
148 0 : return false;
149 :
150 1 : torture_comment(tctx, "TESTING SETFILEINFO EA_SET\n");
151 :
152 1 : io.generic.level = RAW_OPEN_NTCREATEX;
153 1 : io.ntcreatex.in.root_fid.fnum = 0;
154 1 : io.ntcreatex.in.flags = 0;
155 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
156 1 : io.ntcreatex.in.create_options = 0;
157 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
158 1 : io.ntcreatex.in.share_access =
159 : NTCREATEX_SHARE_ACCESS_READ |
160 : NTCREATEX_SHARE_ACCESS_WRITE;
161 1 : io.ntcreatex.in.alloc_size = 0;
162 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
163 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
164 1 : io.ntcreatex.in.security_flags = 0;
165 1 : io.ntcreatex.in.fname = fname;
166 1 : status = smb_raw_open(cli->tree, tctx, &io);
167 1 : CHECK_STATUS(status, NT_STATUS_OK);
168 1 : fnum = io.ntcreatex.out.file.fnum;
169 :
170 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
171 1 : q.query_secdesc.in.file.fnum = fnum;
172 1 : q.query_secdesc.in.secinfo_flags =
173 : SECINFO_OWNER |
174 : SECINFO_GROUP |
175 : SECINFO_DACL;
176 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
177 1 : CHECK_STATUS(status, NT_STATUS_OK);
178 1 : sd = q.query_secdesc.out.sd;
179 :
180 1 : torture_comment(tctx, "add a new ACE to the DACL\n");
181 :
182 1 : test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);
183 :
184 1 : ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
185 1 : ace.flags = 0;
186 1 : ace.access_mask = SEC_STD_ALL;
187 1 : ace.trustee = *test_sid;
188 :
189 1 : status = security_descriptor_dacl_add(sd, &ace);
190 1 : CHECK_STATUS(status, NT_STATUS_OK);
191 :
192 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
193 1 : set.set_secdesc.in.file.fnum = fnum;
194 1 : set.set_secdesc.in.secinfo_flags = q.query_secdesc.in.secinfo_flags;
195 1 : set.set_secdesc.in.sd = sd;
196 :
197 1 : status = smb_raw_setfileinfo(cli->tree, &set);
198 1 : CHECK_STATUS(status, NT_STATUS_OK);
199 1 : FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
200 :
201 1 : torture_comment(tctx, "remove it again\n");
202 :
203 1 : status = security_descriptor_dacl_del(sd, test_sid);
204 1 : CHECK_STATUS(status, NT_STATUS_OK);
205 :
206 1 : status = smb_raw_setfileinfo(cli->tree, &set);
207 1 : CHECK_STATUS(status, NT_STATUS_OK);
208 1 : FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
209 :
210 1 : done:
211 1 : smbcli_close(cli->tree, fnum);
212 1 : smb_raw_exit(cli->session);
213 1 : smbcli_deltree(cli->tree, BASEDIR);
214 :
215 1 : return ret;
216 : }
217 :
218 :
219 : /*
220 : test using nttrans create to create a file with an initial acl set
221 : Test copied to test_create_acl() for SMB2.
222 : */
223 2 : static bool test_nttrans_create_ext(struct torture_context *tctx,
224 : struct smbcli_state *cli, bool test_dir)
225 : {
226 : NTSTATUS status;
227 : union smb_open io;
228 2 : const char *fname = BASEDIR "\\acl2.txt";
229 2 : bool ret = true;
230 2 : int fnum = -1;
231 2 : union smb_fileinfo q = {};
232 : struct security_ace ace;
233 : struct security_descriptor *sd;
234 : struct dom_sid *test_sid;
235 2 : uint32_t attrib =
236 : FILE_ATTRIBUTE_HIDDEN |
237 : FILE_ATTRIBUTE_SYSTEM |
238 : (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
239 2 : NTSTATUS (*delete_func)(struct smbcli_tree *, const char *) =
240 2 : test_dir ? smbcli_rmdir : smbcli_unlink;
241 :
242 2 : ZERO_STRUCT(ace);
243 :
244 2 : if (!torture_setup_dir(cli, BASEDIR))
245 0 : return false;
246 :
247 2 : io.generic.level = RAW_OPEN_NTTRANS_CREATE;
248 2 : io.ntcreatex.in.root_fid.fnum = 0;
249 2 : io.ntcreatex.in.flags = 0;
250 2 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
251 2 : io.ntcreatex.in.create_options =
252 2 : test_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
253 2 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
254 2 : io.ntcreatex.in.share_access =
255 : NTCREATEX_SHARE_ACCESS_READ |
256 : NTCREATEX_SHARE_ACCESS_WRITE;
257 2 : io.ntcreatex.in.alloc_size = 0;
258 2 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
259 2 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
260 2 : io.ntcreatex.in.security_flags = 0;
261 2 : io.ntcreatex.in.fname = fname;
262 2 : io.ntcreatex.in.sec_desc = NULL;
263 2 : io.ntcreatex.in.ea_list = NULL;
264 :
265 2 : torture_comment(tctx, "basic create\n");
266 :
267 2 : status = smb_raw_open(cli->tree, tctx, &io);
268 2 : CHECK_STATUS(status, NT_STATUS_OK);
269 2 : fnum = io.ntcreatex.out.file.fnum;
270 :
271 2 : torture_comment(tctx, "querying ACL\n");
272 :
273 2 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
274 2 : q.query_secdesc.in.file.fnum = fnum;
275 2 : q.query_secdesc.in.secinfo_flags =
276 : SECINFO_OWNER |
277 : SECINFO_GROUP |
278 : SECINFO_DACL;
279 2 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
280 2 : CHECK_STATUS(status, NT_STATUS_OK);
281 2 : sd = q.query_secdesc.out.sd;
282 :
283 2 : status = smbcli_close(cli->tree, fnum);
284 2 : CHECK_STATUS(status, NT_STATUS_OK);
285 :
286 2 : status = delete_func(cli->tree, fname);
287 2 : CHECK_STATUS(status, NT_STATUS_OK);
288 :
289 2 : torture_comment(tctx, "adding a new ACE\n");
290 2 : test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);
291 :
292 2 : ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
293 2 : ace.flags = 0;
294 2 : ace.access_mask = SEC_STD_ALL;
295 2 : ace.trustee = *test_sid;
296 :
297 2 : status = security_descriptor_dacl_add(sd, &ace);
298 2 : CHECK_STATUS(status, NT_STATUS_OK);
299 :
300 2 : torture_comment(tctx, "creating with an initial ACL\n");
301 :
302 2 : io.ntcreatex.in.sec_desc = sd;
303 2 : status = smb_raw_open(cli->tree, tctx, &io);
304 2 : CHECK_STATUS(status, NT_STATUS_OK);
305 2 : fnum = io.ntcreatex.out.file.fnum;
306 :
307 2 : FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
308 :
309 2 : status = smbcli_close(cli->tree, fnum);
310 2 : CHECK_STATUS(status, NT_STATUS_OK);
311 2 : status = delete_func(cli->tree, fname);
312 2 : CHECK_STATUS(status, NT_STATUS_OK);
313 :
314 2 : torture_comment(tctx, "creating with attributes\n");
315 :
316 2 : io.ntcreatex.in.sec_desc = NULL;
317 2 : io.ntcreatex.in.file_attr = attrib;
318 2 : status = smb_raw_open(cli->tree, tctx, &io);
319 2 : CHECK_STATUS(status, NT_STATUS_OK);
320 2 : fnum = io.ntcreatex.out.file.fnum;
321 :
322 2 : FAIL_UNLESS(verify_attrib(tctx, cli, fnum, attrib));
323 :
324 1 : status = smbcli_close(cli->tree, fnum);
325 1 : CHECK_STATUS(status, NT_STATUS_OK);
326 :
327 1 : status = delete_func(cli->tree, fname);
328 1 : CHECK_STATUS(status, NT_STATUS_OK);
329 :
330 1 : torture_comment(tctx, "creating with attributes and ACL\n");
331 :
332 1 : io.ntcreatex.in.sec_desc = sd;
333 1 : io.ntcreatex.in.file_attr = attrib;
334 1 : status = smb_raw_open(cli->tree, tctx, &io);
335 1 : CHECK_STATUS(status, NT_STATUS_OK);
336 1 : fnum = io.ntcreatex.out.file.fnum;
337 :
338 1 : FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
339 1 : FAIL_UNLESS(verify_attrib(tctx, cli, fnum, attrib));
340 :
341 1 : status = smbcli_close(cli->tree, fnum);
342 1 : CHECK_STATUS(status, NT_STATUS_OK);
343 1 : status = delete_func(cli->tree, fname);
344 1 : CHECK_STATUS(status, NT_STATUS_OK);
345 :
346 3 : done:
347 2 : smbcli_close(cli->tree, fnum);
348 2 : smb_raw_exit(cli->session);
349 2 : smbcli_deltree(cli->tree, BASEDIR);
350 2 : return ret;
351 : }
352 :
353 : /*
354 : test using nttrans create to create a file and directory with an initial acl
355 : and owner.
356 : */
357 2 : static bool test_nttrans_create_ext_owner(
358 : struct torture_context *tctx,
359 : struct smbcli_state *cli, bool test_dir)
360 : {
361 : NTSTATUS status;
362 : union smb_open io;
363 2 : const char *fname = BASEDIR "\\foo.txt";
364 2 : bool ret = true;
365 2 : int fnum = -1;
366 : struct security_ace ace;
367 : struct security_descriptor *sd;
368 2 : uint32_t attrib =
369 : FILE_ATTRIBUTE_HIDDEN |
370 : FILE_ATTRIBUTE_SYSTEM |
371 : (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
372 2 : NTSTATUS (*delete_func)(struct smbcli_tree *, const char *) =
373 2 : test_dir ? smbcli_rmdir : smbcli_unlink;
374 :
375 2 : ZERO_STRUCT(ace);
376 :
377 2 : smbcli_deltree(cli->tree, BASEDIR);
378 :
379 2 : if (!torture_setup_dir(cli, BASEDIR))
380 0 : return false;
381 :
382 2 : io.generic.level = RAW_OPEN_NTTRANS_CREATE;
383 2 : io.ntcreatex.in.root_fid.fnum = 0;
384 2 : io.ntcreatex.in.flags = 0;
385 2 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
386 2 : io.ntcreatex.in.create_options =
387 2 : test_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
388 2 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
389 2 : io.ntcreatex.in.share_access =
390 : NTCREATEX_SHARE_ACCESS_READ |
391 : NTCREATEX_SHARE_ACCESS_WRITE;
392 2 : io.ntcreatex.in.alloc_size = 0;
393 2 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
394 2 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
395 2 : io.ntcreatex.in.security_flags = 0;
396 2 : io.ntcreatex.in.fname = fname;
397 2 : io.ntcreatex.in.sec_desc = NULL;
398 2 : io.ntcreatex.in.ea_list = NULL;
399 :
400 2 : torture_comment(tctx, "creating with attributes, ACL and owner\n");
401 :
402 2 : sd = security_descriptor_dacl_create(tctx,
403 : 0, SID_WORLD, SID_BUILTIN_USERS,
404 : SID_WORLD,
405 : SEC_ACE_TYPE_ACCESS_ALLOWED,
406 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
407 : 0,
408 : NULL);
409 :
410 2 : io.ntcreatex.in.sec_desc = sd;
411 2 : io.ntcreatex.in.file_attr = attrib;
412 2 : status = smb_raw_open(cli->tree, tctx, &io);
413 2 : CHECK_STATUS(status, NT_STATUS_OK);
414 2 : fnum = io.ntcreatex.out.file.fnum;
415 :
416 2 : FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
417 0 : FAIL_UNLESS(verify_attrib(tctx, cli, fnum, attrib));
418 :
419 0 : status = smbcli_close(cli->tree, fnum);
420 0 : CHECK_STATUS(status, NT_STATUS_OK);
421 0 : status = delete_func(cli->tree, fname);
422 0 : CHECK_STATUS(status, NT_STATUS_OK);
423 :
424 2 : done:
425 2 : smbcli_close(cli->tree, fnum);
426 2 : smb_raw_exit(cli->session);
427 2 : smbcli_deltree(cli->tree, BASEDIR);
428 2 : return ret;
429 : }
430 :
431 1 : static bool test_nttrans_create_file(struct torture_context *tctx,
432 : struct smbcli_state *cli)
433 : {
434 1 : torture_comment(tctx, "Testing nttrans create with sec_desc on files\n");
435 :
436 1 : return test_nttrans_create_ext(tctx, cli, false);
437 : }
438 :
439 1 : static bool test_nttrans_create_dir(struct torture_context *tctx,
440 : struct smbcli_state *cli)
441 : {
442 1 : torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n");
443 :
444 1 : return test_nttrans_create_ext(tctx, cli, true);
445 : }
446 :
447 1 : static bool test_nttrans_create_owner_file(struct torture_context *tctx,
448 : struct smbcli_state *cli)
449 : {
450 1 : torture_comment(tctx, "Testing nttrans create with sec_desc with owner on file\n");
451 :
452 1 : return test_nttrans_create_ext_owner(tctx, cli, false);
453 : }
454 :
455 1 : static bool test_nttrans_create_owner_dir(struct torture_context *tctx,
456 : struct smbcli_state *cli)
457 : {
458 1 : torture_comment(tctx, "Testing nttrans create with sec_desc with owner on directory\n");
459 :
460 1 : return test_nttrans_create_ext_owner(tctx, cli, true);
461 : }
462 :
463 : #define CHECK_ACCESS_FLAGS(_fnum, flags) do { \
464 : union smb_fileinfo _q; \
465 : _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
466 : _q.access_information.in.file.fnum = (_fnum); \
467 : status = smb_raw_fileinfo(cli->tree, tctx, &_q); \
468 : CHECK_STATUS(status, NT_STATUS_OK); \
469 : if (_q.access_information.out.access_flags != (flags)) { \
470 : ret = false; \
471 : torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
472 : __location__, _q.access_information.out.access_flags, (flags)); \
473 : goto done; \
474 : } \
475 : } while (0)
476 :
477 : /*
478 : test using NTTRANS CREATE to create a file with a null ACL set
479 : Test copied to test_create_null_dacl() for SMB2.
480 : */
481 1 : static bool test_nttrans_create_null_dacl(struct torture_context *tctx,
482 : struct smbcli_state *cli)
483 : {
484 : NTSTATUS status;
485 : union smb_open io;
486 1 : const char *fname = BASEDIR "\\nulldacl.txt";
487 1 : bool ret = true;
488 1 : int fnum = -1;
489 : union smb_fileinfo q;
490 : union smb_setfileinfo s;
491 1 : struct security_descriptor *sd = security_descriptor_initialise(tctx);
492 : struct security_acl dacl;
493 :
494 1 : if (!torture_setup_dir(cli, BASEDIR))
495 0 : return false;
496 :
497 1 : torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");
498 :
499 1 : io.generic.level = RAW_OPEN_NTTRANS_CREATE;
500 1 : io.ntcreatex.in.root_fid.fnum = 0;
501 1 : io.ntcreatex.in.flags = 0;
502 1 : io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
503 : | SEC_STD_WRITE_OWNER;
504 1 : io.ntcreatex.in.create_options = 0;
505 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
506 1 : io.ntcreatex.in.share_access =
507 : NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
508 1 : io.ntcreatex.in.alloc_size = 0;
509 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
510 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
511 1 : io.ntcreatex.in.security_flags = 0;
512 1 : io.ntcreatex.in.fname = fname;
513 1 : io.ntcreatex.in.sec_desc = sd;
514 1 : io.ntcreatex.in.ea_list = NULL;
515 :
516 1 : torture_comment(tctx, "creating a file with a empty sd\n");
517 1 : status = smb_raw_open(cli->tree, tctx, &io);
518 1 : CHECK_STATUS(status, NT_STATUS_OK);
519 1 : fnum = io.ntcreatex.out.file.fnum;
520 :
521 1 : torture_comment(tctx, "get the original sd\n");
522 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
523 1 : q.query_secdesc.in.file.fnum = fnum;
524 1 : q.query_secdesc.in.secinfo_flags =
525 : SECINFO_OWNER |
526 : SECINFO_GROUP |
527 : SECINFO_DACL;
528 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
529 1 : CHECK_STATUS(status, NT_STATUS_OK);
530 :
531 : /*
532 : * Testing the created DACL,
533 : * the server should add the inherited DACL
534 : * when SEC_DESC_DACL_PRESENT isn't specified
535 : */
536 1 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
537 0 : ret = false;
538 0 : torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
539 0 : goto done;
540 : }
541 1 : if (q.query_secdesc.out.sd->dacl == NULL) {
542 0 : ret = false;
543 0 : torture_result(tctx, TORTURE_FAIL, "no DACL has been created on the server!\n");
544 0 : goto done;
545 : }
546 :
547 1 : torture_comment(tctx, "set NULL DACL\n");
548 1 : sd->type |= SEC_DESC_DACL_PRESENT;
549 :
550 1 : s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
551 1 : s.set_secdesc.in.file.fnum = fnum;
552 1 : s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
553 1 : s.set_secdesc.in.sd = sd;
554 1 : status = smb_raw_setfileinfo(cli->tree, &s);
555 1 : CHECK_STATUS(status, NT_STATUS_OK);
556 :
557 1 : torture_comment(tctx, "get the sd\n");
558 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
559 1 : q.query_secdesc.in.file.fnum = fnum;
560 1 : q.query_secdesc.in.secinfo_flags =
561 : SECINFO_OWNER |
562 : SECINFO_GROUP |
563 : SECINFO_DACL;
564 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
565 1 : CHECK_STATUS(status, NT_STATUS_OK);
566 :
567 : /* Testing the modified DACL */
568 1 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
569 0 : ret = false;
570 0 : torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
571 0 : goto done;
572 : }
573 1 : if (q.query_secdesc.out.sd->dacl != NULL) {
574 0 : ret = false;
575 0 : torture_result(tctx, TORTURE_FAIL, "DACL has been created on the server!\n");
576 0 : goto done;
577 : }
578 :
579 1 : torture_comment(tctx, "try open for read control\n");
580 1 : io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL;
581 1 : status = smb_raw_open(cli->tree, tctx, &io);
582 1 : CHECK_STATUS(status, NT_STATUS_OK);
583 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
584 : SEC_STD_READ_CONTROL | SEC_FILE_READ_ATTRIBUTE);
585 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
586 :
587 1 : torture_comment(tctx, "try open for write\n");
588 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
589 1 : status = smb_raw_open(cli->tree, tctx, &io);
590 1 : CHECK_STATUS(status, NT_STATUS_OK);
591 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
592 : SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
593 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
594 :
595 1 : torture_comment(tctx, "try open for read\n");
596 1 : io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
597 1 : status = smb_raw_open(cli->tree, tctx, &io);
598 1 : CHECK_STATUS(status, NT_STATUS_OK);
599 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
600 : SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE);
601 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
602 :
603 1 : torture_comment(tctx, "try open for generic write\n");
604 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
605 1 : status = smb_raw_open(cli->tree, tctx, &io);
606 1 : CHECK_STATUS(status, NT_STATUS_OK);
607 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
608 : SEC_RIGHTS_FILE_WRITE | SEC_FILE_READ_ATTRIBUTE);
609 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
610 :
611 1 : torture_comment(tctx, "try open for generic read\n");
612 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
613 1 : status = smb_raw_open(cli->tree, tctx, &io);
614 1 : CHECK_STATUS(status, NT_STATUS_OK);
615 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
616 : SEC_RIGHTS_FILE_READ | SEC_FILE_READ_ATTRIBUTE);
617 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
618 :
619 1 : torture_comment(tctx, "set DACL with 0 aces\n");
620 1 : ZERO_STRUCT(dacl);
621 1 : dacl.revision = SECURITY_ACL_REVISION_NT4;
622 1 : dacl.num_aces = 0;
623 1 : sd->dacl = &dacl;
624 :
625 1 : s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
626 1 : s.set_secdesc.in.file.fnum = fnum;
627 1 : s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
628 1 : s.set_secdesc.in.sd = sd;
629 1 : status = smb_raw_setfileinfo(cli->tree, &s);
630 1 : CHECK_STATUS(status, NT_STATUS_OK);
631 :
632 1 : torture_comment(tctx, "get the sd\n");
633 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
634 1 : q.query_secdesc.in.file.fnum = fnum;
635 1 : q.query_secdesc.in.secinfo_flags =
636 : SECINFO_OWNER |
637 : SECINFO_GROUP |
638 : SECINFO_DACL;
639 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
640 1 : CHECK_STATUS(status, NT_STATUS_OK);
641 :
642 : /* Testing the modified DACL */
643 1 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
644 0 : ret = false;
645 0 : torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
646 0 : goto done;
647 : }
648 1 : if (q.query_secdesc.out.sd->dacl == NULL) {
649 0 : ret = false;
650 0 : torture_result(tctx, TORTURE_FAIL, "no DACL has been created on the server!\n");
651 0 : goto done;
652 : }
653 1 : if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
654 0 : ret = false;
655 0 : torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
656 0 : q.query_secdesc.out.sd->dacl->num_aces);
657 0 : goto done;
658 : }
659 :
660 1 : torture_comment(tctx, "try open for read control\n");
661 1 : io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL;
662 1 : status = smb_raw_open(cli->tree, tctx, &io);
663 1 : CHECK_STATUS(status, NT_STATUS_OK);
664 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
665 : SEC_STD_READ_CONTROL | SEC_FILE_READ_ATTRIBUTE);
666 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
667 :
668 1 : torture_comment(tctx, "try open for write => access_denied\n");
669 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
670 1 : status = smb_raw_open(cli->tree, tctx, &io);
671 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
672 :
673 1 : torture_comment(tctx, "try open for read => access_denied\n");
674 1 : io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
675 1 : status = smb_raw_open(cli->tree, tctx, &io);
676 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
677 :
678 1 : torture_comment(tctx, "try open for generic write => access_denied\n");
679 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
680 1 : status = smb_raw_open(cli->tree, tctx, &io);
681 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
682 :
683 1 : torture_comment(tctx, "try open for generic read => access_denied\n");
684 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
685 1 : status = smb_raw_open(cli->tree, tctx, &io);
686 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
687 :
688 1 : torture_comment(tctx, "set empty sd\n");
689 1 : sd->type &= ~SEC_DESC_DACL_PRESENT;
690 1 : sd->dacl = NULL;
691 :
692 1 : s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
693 1 : s.set_secdesc.in.file.fnum = fnum;
694 1 : s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
695 1 : s.set_secdesc.in.sd = sd;
696 1 : status = smb_raw_setfileinfo(cli->tree, &s);
697 1 : CHECK_STATUS(status, NT_STATUS_OK);
698 :
699 1 : torture_comment(tctx, "get the sd\n");
700 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
701 1 : q.query_secdesc.in.file.fnum = fnum;
702 1 : q.query_secdesc.in.secinfo_flags =
703 : SECINFO_OWNER |
704 : SECINFO_GROUP |
705 : SECINFO_DACL;
706 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
707 1 : CHECK_STATUS(status, NT_STATUS_OK);
708 :
709 : /* Testing the modified DACL */
710 1 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
711 0 : ret = false;
712 0 : torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
713 0 : goto done;
714 : }
715 1 : if (q.query_secdesc.out.sd->dacl != NULL) {
716 0 : ret = false;
717 0 : torture_result(tctx, TORTURE_FAIL, "DACL has been created on the server!\n");
718 0 : goto done;
719 : }
720 2 : done:
721 1 : smbcli_close(cli->tree, fnum);
722 1 : smb_raw_exit(cli->session);
723 1 : smbcli_deltree(cli->tree, BASEDIR);
724 1 : return ret;
725 : }
726 :
727 : /*
728 : test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
729 : mapping bits
730 : Test copied to smb2/acls.c for SMB2.
731 : */
732 1 : static bool test_creator_sid(struct torture_context *tctx,
733 : struct smbcli_state *cli)
734 : {
735 : NTSTATUS status;
736 : union smb_open io;
737 1 : const char *fname = BASEDIR "\\creator.txt";
738 1 : bool ret = true;
739 1 : int fnum = -1;
740 : union smb_fileinfo q;
741 : union smb_setfileinfo set;
742 : struct security_descriptor *sd, *sd_orig, *sd2;
743 : const char *owner_sid;
744 :
745 1 : if (!torture_setup_dir(cli, BASEDIR))
746 0 : return false;
747 :
748 1 : torture_comment(tctx, "TESTING SID_CREATOR_OWNER\n");
749 :
750 1 : io.generic.level = RAW_OPEN_NTCREATEX;
751 1 : io.ntcreatex.in.root_fid.fnum = 0;
752 1 : io.ntcreatex.in.flags = 0;
753 1 : io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER;
754 1 : io.ntcreatex.in.create_options = 0;
755 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
756 1 : io.ntcreatex.in.share_access =
757 : NTCREATEX_SHARE_ACCESS_READ |
758 : NTCREATEX_SHARE_ACCESS_WRITE;
759 1 : io.ntcreatex.in.alloc_size = 0;
760 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
761 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
762 1 : io.ntcreatex.in.security_flags = 0;
763 1 : io.ntcreatex.in.fname = fname;
764 1 : status = smb_raw_open(cli->tree, tctx, &io);
765 1 : CHECK_STATUS(status, NT_STATUS_OK);
766 1 : fnum = io.ntcreatex.out.file.fnum;
767 :
768 1 : torture_comment(tctx, "get the original sd\n");
769 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
770 1 : q.query_secdesc.in.file.fnum = fnum;
771 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
772 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
773 1 : CHECK_STATUS(status, NT_STATUS_OK);
774 1 : sd_orig = q.query_secdesc.out.sd;
775 :
776 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
777 :
778 1 : torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n");
779 1 : sd = security_descriptor_dacl_create(tctx,
780 : 0, NULL, NULL,
781 : SID_CREATOR_OWNER,
782 : SEC_ACE_TYPE_ACCESS_ALLOWED,
783 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
784 : 0,
785 : NULL);
786 :
787 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
788 1 : set.set_secdesc.in.file.fnum = fnum;
789 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
790 1 : set.set_secdesc.in.sd = sd;
791 :
792 1 : status = smb_raw_setfileinfo(cli->tree, &set);
793 1 : CHECK_STATUS(status, NT_STATUS_OK);
794 :
795 1 : torture_comment(tctx, "try open for write\n");
796 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
797 1 : status = smb_raw_open(cli->tree, tctx, &io);
798 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
799 :
800 1 : torture_comment(tctx, "try open for read\n");
801 1 : io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
802 1 : status = smb_raw_open(cli->tree, tctx, &io);
803 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
804 :
805 1 : torture_comment(tctx, "try open for generic write\n");
806 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
807 1 : status = smb_raw_open(cli->tree, tctx, &io);
808 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
809 :
810 1 : torture_comment(tctx, "try open for generic read\n");
811 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
812 1 : status = smb_raw_open(cli->tree, tctx, &io);
813 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
814 :
815 1 : torture_comment(tctx, "set a sec desc allowing no write by owner\n");
816 1 : sd = security_descriptor_dacl_create(tctx,
817 : 0, owner_sid, NULL,
818 : owner_sid,
819 : SEC_ACE_TYPE_ACCESS_ALLOWED,
820 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
821 : 0,
822 : NULL);
823 :
824 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
825 1 : set.set_secdesc.in.file.fnum = fnum;
826 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
827 1 : set.set_secdesc.in.sd = sd;
828 1 : status = smb_raw_setfileinfo(cli->tree, &set);
829 1 : CHECK_STATUS(status, NT_STATUS_OK);
830 :
831 1 : torture_comment(tctx, "check that sd has been mapped correctly\n");
832 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
833 1 : CHECK_STATUS(status, NT_STATUS_OK);
834 1 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
835 :
836 1 : torture_comment(tctx, "try open for write\n");
837 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
838 1 : status = smb_raw_open(cli->tree, tctx, &io);
839 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
840 :
841 1 : torture_comment(tctx, "try open for read\n");
842 1 : io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
843 1 : status = smb_raw_open(cli->tree, tctx, &io);
844 1 : CHECK_STATUS(status, NT_STATUS_OK);
845 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
846 : SEC_FILE_READ_DATA|
847 : SEC_FILE_READ_ATTRIBUTE);
848 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
849 :
850 1 : torture_comment(tctx, "try open for generic write\n");
851 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
852 1 : status = smb_raw_open(cli->tree, tctx, &io);
853 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
854 :
855 1 : torture_comment(tctx, "try open for generic read\n");
856 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
857 1 : status = smb_raw_open(cli->tree, tctx, &io);
858 1 : CHECK_STATUS(status, NT_STATUS_OK);
859 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
860 : SEC_RIGHTS_FILE_READ);
861 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
862 :
863 1 : torture_comment(tctx, "set a sec desc allowing generic read by owner\n");
864 1 : sd = security_descriptor_dacl_create(tctx,
865 : 0, NULL, NULL,
866 : owner_sid,
867 : SEC_ACE_TYPE_ACCESS_ALLOWED,
868 : SEC_GENERIC_READ | SEC_STD_ALL,
869 : 0,
870 : NULL);
871 :
872 1 : set.set_secdesc.in.sd = sd;
873 1 : status = smb_raw_setfileinfo(cli->tree, &set);
874 1 : CHECK_STATUS(status, NT_STATUS_OK);
875 :
876 1 : torture_comment(tctx, "check that generic read has been mapped correctly\n");
877 1 : sd2 = security_descriptor_dacl_create(tctx,
878 : 0, owner_sid, NULL,
879 : owner_sid,
880 : SEC_ACE_TYPE_ACCESS_ALLOWED,
881 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
882 : 0,
883 : NULL);
884 :
885 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
886 1 : CHECK_STATUS(status, NT_STATUS_OK);
887 1 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
888 :
889 1 : torture_comment(tctx, "try open for write\n");
890 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
891 1 : status = smb_raw_open(cli->tree, tctx, &io);
892 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
893 :
894 1 : torture_comment(tctx, "try open for read\n");
895 1 : io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
896 1 : status = smb_raw_open(cli->tree, tctx, &io);
897 1 : CHECK_STATUS(status, NT_STATUS_OK);
898 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
899 : SEC_FILE_READ_DATA |
900 : SEC_FILE_READ_ATTRIBUTE);
901 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
902 :
903 1 : torture_comment(tctx, "try open for generic write\n");
904 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
905 1 : status = smb_raw_open(cli->tree, tctx, &io);
906 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
907 :
908 1 : torture_comment(tctx, "try open for generic read\n");
909 1 : io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
910 1 : status = smb_raw_open(cli->tree, tctx, &io);
911 1 : CHECK_STATUS(status, NT_STATUS_OK);
912 1 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, SEC_RIGHTS_FILE_READ);
913 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
914 :
915 :
916 1 : torture_comment(tctx, "put back original sd\n");
917 1 : set.set_secdesc.in.sd = sd_orig;
918 1 : status = smb_raw_setfileinfo(cli->tree, &set);
919 1 : CHECK_STATUS(status, NT_STATUS_OK);
920 :
921 :
922 2 : done:
923 1 : smbcli_close(cli->tree, fnum);
924 1 : smb_raw_exit(cli->session);
925 1 : smbcli_deltree(cli->tree, BASEDIR);
926 1 : return ret;
927 : }
928 :
929 :
930 : /*
931 : test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
932 : SEC_FILE_xx bits
933 : Test copied to smb2/acls.c for SMB2.
934 : */
935 1 : static bool test_generic_bits(struct torture_context *tctx,
936 : struct smbcli_state *cli)
937 : {
938 : NTSTATUS status;
939 : union smb_open io;
940 1 : const char *fname = BASEDIR "\\generic.txt";
941 1 : bool ret = true;
942 1 : int fnum = -1, i;
943 : union smb_fileinfo q;
944 : union smb_setfileinfo set;
945 : struct security_descriptor *sd, *sd_orig, *sd2;
946 : const char *owner_sid;
947 : const struct {
948 : uint32_t gen_bits;
949 : uint32_t specific_bits;
950 1 : } file_mappings[] = {
951 : { 0, 0 },
952 : { SEC_GENERIC_READ, SEC_RIGHTS_FILE_READ },
953 : { SEC_GENERIC_WRITE, SEC_RIGHTS_FILE_WRITE },
954 : { SEC_GENERIC_EXECUTE, SEC_RIGHTS_FILE_EXECUTE },
955 : { SEC_GENERIC_ALL, SEC_RIGHTS_FILE_ALL },
956 : { SEC_FILE_READ_DATA, SEC_FILE_READ_DATA },
957 : { SEC_FILE_READ_ATTRIBUTE, SEC_FILE_READ_ATTRIBUTE }
958 : };
959 : const struct {
960 : uint32_t gen_bits;
961 : uint32_t specific_bits;
962 1 : } dir_mappings[] = {
963 : { 0, 0 },
964 : { SEC_GENERIC_READ, SEC_RIGHTS_DIR_READ },
965 : { SEC_GENERIC_WRITE, SEC_RIGHTS_DIR_WRITE },
966 : { SEC_GENERIC_EXECUTE, SEC_RIGHTS_DIR_EXECUTE },
967 : { SEC_GENERIC_ALL, SEC_RIGHTS_DIR_ALL }
968 : };
969 : bool has_restore_privilege;
970 : bool has_take_ownership_privilege;
971 :
972 1 : if (!torture_setup_dir(cli, BASEDIR))
973 0 : return false;
974 :
975 1 : torture_comment(tctx, "TESTING FILE GENERIC BITS\n");
976 :
977 1 : io.generic.level = RAW_OPEN_NTCREATEX;
978 1 : io.ntcreatex.in.root_fid.fnum = 0;
979 1 : io.ntcreatex.in.flags = 0;
980 1 : io.ntcreatex.in.access_mask =
981 : SEC_STD_READ_CONTROL |
982 : SEC_STD_WRITE_DAC |
983 : SEC_STD_WRITE_OWNER;
984 1 : io.ntcreatex.in.create_options = 0;
985 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
986 1 : io.ntcreatex.in.share_access =
987 : NTCREATEX_SHARE_ACCESS_READ |
988 : NTCREATEX_SHARE_ACCESS_WRITE;
989 1 : io.ntcreatex.in.alloc_size = 0;
990 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
991 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
992 1 : io.ntcreatex.in.security_flags = 0;
993 1 : io.ntcreatex.in.fname = fname;
994 1 : status = smb_raw_open(cli->tree, tctx, &io);
995 1 : CHECK_STATUS(status, NT_STATUS_OK);
996 1 : fnum = io.ntcreatex.out.file.fnum;
997 :
998 1 : torture_comment(tctx, "get the original sd\n");
999 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1000 1 : q.query_secdesc.in.file.fnum = fnum;
1001 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1002 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1003 1 : CHECK_STATUS(status, NT_STATUS_OK);
1004 1 : sd_orig = q.query_secdesc.out.sd;
1005 :
1006 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1007 :
1008 1 : status = torture_check_privilege(cli,
1009 : owner_sid,
1010 : sec_privilege_name(SEC_PRIV_RESTORE));
1011 1 : has_restore_privilege = NT_STATUS_IS_OK(status);
1012 1 : if (!NT_STATUS_IS_OK(status)) {
1013 0 : torture_warning(tctx, "torture_check_privilege - %s\n",
1014 : nt_errstr(status));
1015 : }
1016 1 : torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
1017 :
1018 1 : status = torture_check_privilege(cli,
1019 : owner_sid,
1020 : sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
1021 1 : has_take_ownership_privilege = NT_STATUS_IS_OK(status);
1022 1 : if (!NT_STATUS_IS_OK(status)) {
1023 0 : torture_warning(tctx, "torture_check_privilege - %s\n",
1024 : nt_errstr(status));
1025 : }
1026 1 : torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
1027 :
1028 8 : for (i=0;i<ARRAY_SIZE(file_mappings);i++) {
1029 7 : uint32_t expected_mask =
1030 : SEC_STD_WRITE_DAC |
1031 : SEC_STD_READ_CONTROL |
1032 : SEC_FILE_READ_ATTRIBUTE |
1033 : SEC_STD_DELETE;
1034 7 : uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
1035 :
1036 7 : if (has_restore_privilege) {
1037 7 : expected_mask_anon |= SEC_STD_DELETE;
1038 : }
1039 :
1040 7 : torture_comment(tctx, "Testing generic bits 0x%08x\n",
1041 0 : file_mappings[i].gen_bits);
1042 7 : sd = security_descriptor_dacl_create(tctx,
1043 : 0, owner_sid, NULL,
1044 : owner_sid,
1045 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1046 0 : file_mappings[i].gen_bits,
1047 : 0,
1048 : NULL);
1049 :
1050 7 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1051 7 : set.set_secdesc.in.file.fnum = fnum;
1052 7 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1053 7 : set.set_secdesc.in.sd = sd;
1054 :
1055 7 : status = smb_raw_setfileinfo(cli->tree, &set);
1056 7 : CHECK_STATUS(status, NT_STATUS_OK);
1057 :
1058 7 : sd2 = security_descriptor_dacl_create(tctx,
1059 : 0, owner_sid, NULL,
1060 : owner_sid,
1061 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1062 0 : file_mappings[i].specific_bits,
1063 : 0,
1064 : NULL);
1065 :
1066 7 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1067 7 : CHECK_STATUS(status, NT_STATUS_OK);
1068 7 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1069 :
1070 7 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1071 7 : status = smb_raw_open(cli->tree, tctx, &io);
1072 7 : CHECK_STATUS(status, NT_STATUS_OK);
1073 7 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1074 : expected_mask | file_mappings[i].specific_bits);
1075 7 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1076 :
1077 7 : if (!has_take_ownership_privilege) {
1078 0 : continue;
1079 : }
1080 :
1081 7 : torture_comment(tctx, "Testing generic bits 0x%08x (anonymous)\n",
1082 0 : file_mappings[i].gen_bits);
1083 7 : sd = security_descriptor_dacl_create(tctx,
1084 : 0, SID_NT_ANONYMOUS, NULL,
1085 : owner_sid,
1086 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1087 0 : file_mappings[i].gen_bits,
1088 : 0,
1089 : NULL);
1090 :
1091 7 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1092 7 : set.set_secdesc.in.file.fnum = fnum;
1093 7 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1094 7 : set.set_secdesc.in.sd = sd;
1095 :
1096 7 : status = smb_raw_setfileinfo(cli->tree, &set);
1097 7 : CHECK_STATUS(status, NT_STATUS_OK);
1098 :
1099 7 : sd2 = security_descriptor_dacl_create(tctx,
1100 : 0, SID_NT_ANONYMOUS, NULL,
1101 : owner_sid,
1102 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1103 0 : file_mappings[i].specific_bits,
1104 : 0,
1105 : NULL);
1106 :
1107 7 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1108 7 : CHECK_STATUS(status, NT_STATUS_OK);
1109 7 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1110 :
1111 7 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1112 7 : status = smb_raw_open(cli->tree, tctx, &io);
1113 7 : CHECK_STATUS(status, NT_STATUS_OK);
1114 7 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1115 : expected_mask_anon | file_mappings[i].specific_bits);
1116 7 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1117 : }
1118 :
1119 1 : torture_comment(tctx, "put back original sd\n");
1120 1 : set.set_secdesc.in.sd = sd_orig;
1121 1 : status = smb_raw_setfileinfo(cli->tree, &set);
1122 1 : CHECK_STATUS(status, NT_STATUS_OK);
1123 :
1124 1 : smbcli_close(cli->tree, fnum);
1125 1 : smbcli_unlink(cli->tree, fname);
1126 :
1127 :
1128 1 : torture_comment(tctx, "TESTING DIR GENERIC BITS\n");
1129 :
1130 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1131 1 : io.ntcreatex.in.root_fid.fnum = 0;
1132 1 : io.ntcreatex.in.flags = 0;
1133 1 : io.ntcreatex.in.access_mask =
1134 : SEC_STD_READ_CONTROL |
1135 : SEC_STD_WRITE_DAC |
1136 : SEC_STD_WRITE_OWNER;
1137 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1138 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1139 1 : io.ntcreatex.in.share_access =
1140 : NTCREATEX_SHARE_ACCESS_READ |
1141 : NTCREATEX_SHARE_ACCESS_WRITE;
1142 1 : io.ntcreatex.in.alloc_size = 0;
1143 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1144 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1145 1 : io.ntcreatex.in.security_flags = 0;
1146 1 : io.ntcreatex.in.fname = fname;
1147 1 : status = smb_raw_open(cli->tree, tctx, &io);
1148 1 : CHECK_STATUS(status, NT_STATUS_OK);
1149 1 : fnum = io.ntcreatex.out.file.fnum;
1150 :
1151 1 : torture_comment(tctx, "get the original sd\n");
1152 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1153 1 : q.query_secdesc.in.file.fnum = fnum;
1154 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1155 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1156 1 : CHECK_STATUS(status, NT_STATUS_OK);
1157 1 : sd_orig = q.query_secdesc.out.sd;
1158 :
1159 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1160 :
1161 1 : status = torture_check_privilege(cli,
1162 : owner_sid,
1163 : sec_privilege_name(SEC_PRIV_RESTORE));
1164 1 : has_restore_privilege = NT_STATUS_IS_OK(status);
1165 1 : if (!NT_STATUS_IS_OK(status)) {
1166 0 : torture_warning(tctx, "torture_check_privilege - %s\n",
1167 : nt_errstr(status));
1168 : }
1169 1 : torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
1170 :
1171 1 : status = torture_check_privilege(cli,
1172 : owner_sid,
1173 : sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
1174 1 : has_take_ownership_privilege = NT_STATUS_IS_OK(status);
1175 1 : if (!NT_STATUS_IS_OK(status)) {
1176 0 : torture_warning(tctx, "torture_check_privilege - %s\n",
1177 : nt_errstr(status));
1178 : }
1179 1 : torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
1180 :
1181 6 : for (i=0;i<ARRAY_SIZE(dir_mappings);i++) {
1182 5 : uint32_t expected_mask =
1183 : SEC_STD_WRITE_DAC |
1184 : SEC_STD_READ_CONTROL |
1185 : SEC_FILE_READ_ATTRIBUTE |
1186 : SEC_STD_DELETE;
1187 5 : uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
1188 :
1189 5 : if (has_restore_privilege) {
1190 5 : expected_mask_anon |= SEC_STD_DELETE;
1191 : }
1192 :
1193 5 : torture_comment(tctx, "Testing generic bits 0x%08x\n",
1194 0 : file_mappings[i].gen_bits);
1195 5 : sd = security_descriptor_dacl_create(tctx,
1196 : 0, owner_sid, NULL,
1197 : owner_sid,
1198 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1199 0 : dir_mappings[i].gen_bits,
1200 : 0,
1201 : NULL);
1202 :
1203 5 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1204 5 : set.set_secdesc.in.file.fnum = fnum;
1205 5 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1206 5 : set.set_secdesc.in.sd = sd;
1207 :
1208 5 : status = smb_raw_setfileinfo(cli->tree, &set);
1209 5 : CHECK_STATUS(status, NT_STATUS_OK);
1210 :
1211 5 : sd2 = security_descriptor_dacl_create(tctx,
1212 : 0, owner_sid, NULL,
1213 : owner_sid,
1214 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1215 0 : dir_mappings[i].specific_bits,
1216 : 0,
1217 : NULL);
1218 :
1219 5 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1220 5 : CHECK_STATUS(status, NT_STATUS_OK);
1221 5 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1222 :
1223 5 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1224 5 : status = smb_raw_open(cli->tree, tctx, &io);
1225 5 : CHECK_STATUS(status, NT_STATUS_OK);
1226 5 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1227 : expected_mask | dir_mappings[i].specific_bits);
1228 5 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1229 :
1230 5 : if (!has_take_ownership_privilege) {
1231 0 : continue;
1232 : }
1233 :
1234 5 : torture_comment(tctx, "Testing generic bits 0x%08x (anonymous)\n",
1235 0 : file_mappings[i].gen_bits);
1236 5 : sd = security_descriptor_dacl_create(tctx,
1237 : 0, SID_NT_ANONYMOUS, NULL,
1238 : owner_sid,
1239 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1240 0 : file_mappings[i].gen_bits,
1241 : 0,
1242 : NULL);
1243 :
1244 5 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1245 5 : set.set_secdesc.in.file.fnum = fnum;
1246 5 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1247 5 : set.set_secdesc.in.sd = sd;
1248 :
1249 5 : status = smb_raw_setfileinfo(cli->tree, &set);
1250 5 : CHECK_STATUS(status, NT_STATUS_OK);
1251 :
1252 5 : sd2 = security_descriptor_dacl_create(tctx,
1253 : 0, SID_NT_ANONYMOUS, NULL,
1254 : owner_sid,
1255 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1256 0 : file_mappings[i].specific_bits,
1257 : 0,
1258 : NULL);
1259 :
1260 5 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1261 5 : CHECK_STATUS(status, NT_STATUS_OK);
1262 5 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1263 :
1264 5 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1265 5 : status = smb_raw_open(cli->tree, tctx, &io);
1266 5 : CHECK_STATUS(status, NT_STATUS_OK);
1267 5 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1268 : expected_mask_anon | dir_mappings[i].specific_bits);
1269 5 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1270 : }
1271 :
1272 1 : torture_comment(tctx, "put back original sd\n");
1273 1 : set.set_secdesc.in.sd = sd_orig;
1274 1 : status = smb_raw_setfileinfo(cli->tree, &set);
1275 1 : CHECK_STATUS(status, NT_STATUS_OK);
1276 :
1277 1 : smbcli_close(cli->tree, fnum);
1278 1 : smbcli_unlink(cli->tree, fname);
1279 :
1280 1 : done:
1281 1 : smbcli_close(cli->tree, fnum);
1282 1 : smb_raw_exit(cli->session);
1283 1 : smbcli_deltree(cli->tree, BASEDIR);
1284 1 : return ret;
1285 : }
1286 :
1287 :
1288 : /*
1289 : see what access bits the owner of a file always gets
1290 : Test copied to smb2/acls.c for SMB2.
1291 : */
1292 1 : static bool test_owner_bits(struct torture_context *tctx,
1293 : struct smbcli_state *cli)
1294 : {
1295 : NTSTATUS status;
1296 : union smb_open io;
1297 1 : const char *fname = BASEDIR "\\test_owner_bits.txt";
1298 1 : bool ret = true;
1299 1 : int fnum = -1, i;
1300 : union smb_fileinfo q;
1301 : union smb_setfileinfo set;
1302 : struct security_descriptor *sd, *sd_orig;
1303 : const char *owner_sid;
1304 : bool has_restore_privilege;
1305 : bool has_take_ownership_privilege;
1306 : uint32_t expected_bits;
1307 :
1308 1 : if (!torture_setup_dir(cli, BASEDIR))
1309 0 : return false;
1310 :
1311 1 : torture_comment(tctx, "TESTING FILE OWNER BITS\n");
1312 :
1313 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1314 1 : io.ntcreatex.in.root_fid.fnum = 0;
1315 1 : io.ntcreatex.in.flags = 0;
1316 1 : io.ntcreatex.in.access_mask =
1317 : SEC_STD_READ_CONTROL |
1318 : SEC_STD_WRITE_DAC |
1319 : SEC_STD_WRITE_OWNER;
1320 1 : io.ntcreatex.in.create_options = 0;
1321 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1322 1 : io.ntcreatex.in.share_access =
1323 : NTCREATEX_SHARE_ACCESS_READ |
1324 : NTCREATEX_SHARE_ACCESS_WRITE;
1325 1 : io.ntcreatex.in.alloc_size = 0;
1326 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1327 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1328 1 : io.ntcreatex.in.security_flags = 0;
1329 1 : io.ntcreatex.in.fname = fname;
1330 1 : status = smb_raw_open(cli->tree, tctx, &io);
1331 1 : CHECK_STATUS(status, NT_STATUS_OK);
1332 1 : fnum = io.ntcreatex.out.file.fnum;
1333 :
1334 1 : torture_comment(tctx, "get the original sd\n");
1335 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1336 1 : q.query_secdesc.in.file.fnum = fnum;
1337 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1338 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1339 1 : CHECK_STATUS(status, NT_STATUS_OK);
1340 1 : sd_orig = q.query_secdesc.out.sd;
1341 :
1342 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1343 :
1344 1 : status = torture_check_privilege(cli,
1345 : owner_sid,
1346 : sec_privilege_name(SEC_PRIV_RESTORE));
1347 1 : has_restore_privilege = NT_STATUS_IS_OK(status);
1348 1 : if (!NT_STATUS_IS_OK(status)) {
1349 0 : torture_warning(tctx, "torture_check_privilege - %s\n", nt_errstr(status));
1350 : }
1351 1 : torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
1352 :
1353 1 : status = torture_check_privilege(cli,
1354 : owner_sid,
1355 : sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
1356 1 : has_take_ownership_privilege = NT_STATUS_IS_OK(status);
1357 1 : if (!NT_STATUS_IS_OK(status)) {
1358 0 : torture_warning(tctx, "torture_check_privilege - %s\n", nt_errstr(status));
1359 : }
1360 1 : torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
1361 :
1362 1 : sd = security_descriptor_dacl_create(tctx,
1363 : 0, NULL, NULL,
1364 : owner_sid,
1365 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1366 : SEC_FILE_WRITE_DATA,
1367 : 0,
1368 : NULL);
1369 :
1370 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1371 1 : set.set_secdesc.in.file.fnum = fnum;
1372 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1373 1 : set.set_secdesc.in.sd = sd;
1374 :
1375 1 : status = smb_raw_setfileinfo(cli->tree, &set);
1376 1 : CHECK_STATUS(status, NT_STATUS_OK);
1377 :
1378 1 : expected_bits = SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE;
1379 :
1380 17 : for (i=0;i<16;i++) {
1381 16 : uint32_t bit = (1<<i);
1382 16 : io.ntcreatex.in.access_mask = bit;
1383 16 : status = smb_raw_open(cli->tree, tctx, &io);
1384 16 : if (expected_bits & bit) {
1385 2 : if (!NT_STATUS_IS_OK(status)) {
1386 0 : torture_warning(tctx, "failed with access mask 0x%08x of expected 0x%08x\n",
1387 : bit, expected_bits);
1388 : }
1389 2 : CHECK_STATUS(status, NT_STATUS_OK);
1390 2 : CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, bit | SEC_FILE_READ_ATTRIBUTE);
1391 2 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1392 : } else {
1393 14 : if (NT_STATUS_IS_OK(status)) {
1394 0 : torture_warning(tctx, "open succeeded with access mask 0x%08x of "
1395 : "expected 0x%08x - should fail\n",
1396 : bit, expected_bits);
1397 : }
1398 14 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1399 : }
1400 : }
1401 :
1402 1 : torture_comment(tctx, "put back original sd\n");
1403 1 : set.set_secdesc.in.sd = sd_orig;
1404 1 : status = smb_raw_setfileinfo(cli->tree, &set);
1405 1 : CHECK_STATUS(status, NT_STATUS_OK);
1406 :
1407 2 : done:
1408 1 : smbcli_close(cli->tree, fnum);
1409 1 : smbcli_unlink(cli->tree, fname);
1410 1 : smb_raw_exit(cli->session);
1411 1 : smbcli_deltree(cli->tree, BASEDIR);
1412 1 : return ret;
1413 : }
1414 :
1415 :
1416 :
1417 : /*
1418 : test the inheritance of ACL flags onto new files and directories
1419 : Test copied to smb2/acls.c for SMB2.
1420 : */
1421 1 : static bool test_inheritance(struct torture_context *tctx,
1422 : struct smbcli_state *cli)
1423 : {
1424 : NTSTATUS status;
1425 : union smb_open io;
1426 1 : const char *dname = BASEDIR "\\inheritance";
1427 1 : const char *fname1 = BASEDIR "\\inheritance\\testfile";
1428 1 : const char *fname2 = BASEDIR "\\inheritance\\testdir";
1429 1 : bool ret = true;
1430 1 : int fnum=0, fnum2, i;
1431 : union smb_fileinfo q;
1432 : union smb_setfileinfo set;
1433 1 : struct security_descriptor *sd, *sd2, *sd_orig=NULL, *sd_def1, *sd_def2;
1434 : const char *owner_sid, *group_sid;
1435 : const struct dom_sid *creator_owner;
1436 : const struct {
1437 : uint32_t parent_flags;
1438 : uint32_t file_flags;
1439 : uint32_t dir_flags;
1440 1 : } test_flags[] = {
1441 : {
1442 : 0,
1443 : 0,
1444 : 0
1445 : },
1446 : {
1447 : SEC_ACE_FLAG_OBJECT_INHERIT,
1448 : 0,
1449 : SEC_ACE_FLAG_OBJECT_INHERIT |
1450 : SEC_ACE_FLAG_INHERIT_ONLY,
1451 : },
1452 : {
1453 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1454 : 0,
1455 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1456 : },
1457 : {
1458 : SEC_ACE_FLAG_OBJECT_INHERIT |
1459 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1460 : 0,
1461 : SEC_ACE_FLAG_OBJECT_INHERIT |
1462 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1463 : },
1464 : {
1465 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1466 : 0,
1467 : 0,
1468 : },
1469 : {
1470 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1471 : SEC_ACE_FLAG_OBJECT_INHERIT,
1472 : 0,
1473 : 0,
1474 : },
1475 : {
1476 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1477 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1478 : 0,
1479 : 0,
1480 : },
1481 : {
1482 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1483 : SEC_ACE_FLAG_CONTAINER_INHERIT |
1484 : SEC_ACE_FLAG_OBJECT_INHERIT,
1485 : 0,
1486 : 0,
1487 : },
1488 : {
1489 : SEC_ACE_FLAG_INHERIT_ONLY,
1490 : 0,
1491 : 0,
1492 : },
1493 : {
1494 : SEC_ACE_FLAG_INHERIT_ONLY |
1495 : SEC_ACE_FLAG_OBJECT_INHERIT,
1496 : 0,
1497 : SEC_ACE_FLAG_OBJECT_INHERIT |
1498 : SEC_ACE_FLAG_INHERIT_ONLY,
1499 : },
1500 : {
1501 : SEC_ACE_FLAG_INHERIT_ONLY |
1502 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1503 : 0,
1504 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1505 : },
1506 : {
1507 : SEC_ACE_FLAG_INHERIT_ONLY |
1508 : SEC_ACE_FLAG_CONTAINER_INHERIT |
1509 : SEC_ACE_FLAG_OBJECT_INHERIT,
1510 : 0,
1511 : SEC_ACE_FLAG_CONTAINER_INHERIT |
1512 : SEC_ACE_FLAG_OBJECT_INHERIT,
1513 : },
1514 : {
1515 : SEC_ACE_FLAG_INHERIT_ONLY |
1516 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1517 : 0,
1518 : 0,
1519 : },
1520 : {
1521 : SEC_ACE_FLAG_INHERIT_ONLY |
1522 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1523 : SEC_ACE_FLAG_OBJECT_INHERIT,
1524 : 0,
1525 : 0,
1526 : },
1527 : {
1528 : SEC_ACE_FLAG_INHERIT_ONLY |
1529 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1530 : SEC_ACE_FLAG_CONTAINER_INHERIT,
1531 : 0,
1532 : 0,
1533 : },
1534 : {
1535 : SEC_ACE_FLAG_INHERIT_ONLY |
1536 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1537 : SEC_ACE_FLAG_CONTAINER_INHERIT |
1538 : SEC_ACE_FLAG_OBJECT_INHERIT,
1539 : 0,
1540 : 0,
1541 : }
1542 : };
1543 :
1544 1 : if (!torture_setup_dir(cli, BASEDIR))
1545 0 : return false;
1546 :
1547 1 : torture_comment(tctx, "TESTING ACL INHERITANCE\n");
1548 :
1549 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1550 1 : io.ntcreatex.in.root_fid.fnum = 0;
1551 1 : io.ntcreatex.in.flags = 0;
1552 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1553 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1554 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1555 1 : io.ntcreatex.in.share_access = 0;
1556 1 : io.ntcreatex.in.alloc_size = 0;
1557 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1558 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1559 1 : io.ntcreatex.in.security_flags = 0;
1560 1 : io.ntcreatex.in.fname = dname;
1561 :
1562 1 : status = smb_raw_open(cli->tree, tctx, &io);
1563 1 : CHECK_STATUS(status, NT_STATUS_OK);
1564 1 : fnum = io.ntcreatex.out.file.fnum;
1565 :
1566 1 : torture_comment(tctx, "get the original sd\n");
1567 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1568 1 : q.query_secdesc.in.file.fnum = fnum;
1569 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
1570 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1571 1 : CHECK_STATUS(status, NT_STATUS_OK);
1572 1 : sd_orig = q.query_secdesc.out.sd;
1573 :
1574 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1575 1 : group_sid = dom_sid_string(tctx, sd_orig->group_sid);
1576 :
1577 1 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
1578 1 : torture_comment(tctx, "group_sid is %s\n", group_sid);
1579 :
1580 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1581 :
1582 1 : if (torture_setting_bool(tctx, "samba4", false)) {
1583 : /* the default ACL in Samba4 includes the group and
1584 : other permissions */
1585 1 : sd_def1 = security_descriptor_dacl_create(tctx,
1586 : 0, owner_sid, NULL,
1587 : owner_sid,
1588 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1589 : SEC_RIGHTS_FILE_ALL,
1590 : 0,
1591 : group_sid,
1592 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1593 : SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE,
1594 : 0,
1595 : SID_WORLD,
1596 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1597 : SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE,
1598 : 0,
1599 : SID_NT_SYSTEM,
1600 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1601 : SEC_RIGHTS_FILE_ALL,
1602 : 0,
1603 : NULL);
1604 : } else {
1605 : /*
1606 : * The Windows Default ACL for a new file, when there is no ACL to be
1607 : * inherited: FullControl for the owner and SYSTEM.
1608 : */
1609 0 : sd_def1 = security_descriptor_dacl_create(tctx,
1610 : 0, owner_sid, NULL,
1611 : owner_sid,
1612 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1613 : SEC_RIGHTS_FILE_ALL,
1614 : 0,
1615 : SID_NT_SYSTEM,
1616 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1617 : SEC_RIGHTS_FILE_ALL,
1618 : 0,
1619 : NULL);
1620 : }
1621 :
1622 : /*
1623 : * Use this in the case the system being tested does not add an ACE for
1624 : * the SYSTEM SID.
1625 : */
1626 1 : sd_def2 = security_descriptor_dacl_create(tctx,
1627 : 0, owner_sid, NULL,
1628 : owner_sid,
1629 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1630 : SEC_RIGHTS_FILE_ALL,
1631 : 0,
1632 : NULL);
1633 :
1634 1 : creator_owner = dom_sid_parse_talloc(tctx, SID_CREATOR_OWNER);
1635 :
1636 17 : for (i=0;i<ARRAY_SIZE(test_flags);i++) {
1637 16 : sd = security_descriptor_dacl_create(tctx,
1638 : 0, NULL, NULL,
1639 : SID_CREATOR_OWNER,
1640 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1641 : SEC_FILE_WRITE_DATA,
1642 0 : test_flags[i].parent_flags,
1643 : SID_WORLD,
1644 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1645 : SEC_FILE_ALL | SEC_STD_ALL,
1646 : 0,
1647 : NULL);
1648 16 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1649 16 : set.set_secdesc.in.file.fnum = fnum;
1650 16 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1651 16 : set.set_secdesc.in.sd = sd;
1652 16 : status = smb_raw_setfileinfo(cli->tree, &set);
1653 16 : CHECK_STATUS(status, NT_STATUS_OK);
1654 :
1655 16 : io.ntcreatex.in.fname = fname1;
1656 16 : io.ntcreatex.in.create_options = 0;
1657 16 : status = smb_raw_open(cli->tree, tctx, &io);
1658 16 : CHECK_STATUS(status, NT_STATUS_OK);
1659 16 : fnum2 = io.ntcreatex.out.file.fnum;
1660 :
1661 16 : q.query_secdesc.in.file.fnum = fnum2;
1662 16 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1663 16 : CHECK_STATUS(status, NT_STATUS_OK);
1664 :
1665 16 : smbcli_close(cli->tree, fnum2);
1666 16 : smbcli_unlink(cli->tree, fname1);
1667 :
1668 16 : if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
1669 8 : if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def1) &&
1670 0 : !security_descriptor_equal(q.query_secdesc.out.sd, sd_def2)) {
1671 0 : torture_warning(tctx, "Expected default sd "
1672 : "for i=%d:\n", i);
1673 0 : NDR_PRINT_DEBUG(security_descriptor, sd_def1);
1674 0 : torture_warning(tctx, "at %d - got:\n", i);
1675 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1676 : }
1677 8 : goto check_dir;
1678 : }
1679 :
1680 16 : if (q.query_secdesc.out.sd->dacl == NULL ||
1681 16 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1682 16 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1683 8 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1684 8 : sd_orig->owner_sid)) {
1685 0 : ret = false;
1686 0 : torture_warning(tctx, "Bad sd in child file at %d\n", i);
1687 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1688 0 : goto check_dir;
1689 : }
1690 :
1691 16 : if (q.query_secdesc.out.sd->dacl->aces[0].flags !=
1692 8 : test_flags[i].file_flags) {
1693 0 : torture_warning(tctx, "incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1694 0 : q.query_secdesc.out.sd->dacl->aces[0].flags,
1695 0 : test_flags[i].file_flags,
1696 0 : test_flags[i].parent_flags,
1697 : i);
1698 0 : ret = false;
1699 : }
1700 :
1701 24 : check_dir:
1702 16 : io.ntcreatex.in.fname = fname2;
1703 16 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1704 16 : status = smb_raw_open(cli->tree, tctx, &io);
1705 16 : CHECK_STATUS(status, NT_STATUS_OK);
1706 16 : fnum2 = io.ntcreatex.out.file.fnum;
1707 :
1708 16 : q.query_secdesc.in.file.fnum = fnum2;
1709 16 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1710 16 : CHECK_STATUS(status, NT_STATUS_OK);
1711 :
1712 16 : smbcli_close(cli->tree, fnum2);
1713 16 : smbcli_rmdir(cli->tree, fname2);
1714 :
1715 24 : if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1716 12 : (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT) ||
1717 4 : (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT))) {
1718 6 : if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def1) &&
1719 0 : !security_descriptor_equal(q.query_secdesc.out.sd, sd_def2)) {
1720 0 : torture_warning(tctx, "Expected default sd for dir at %d:\n", i);
1721 0 : NDR_PRINT_DEBUG(security_descriptor, sd_def1);
1722 0 : torture_warning(tctx, "got:\n");
1723 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1724 : }
1725 6 : continue;
1726 : }
1727 :
1728 18 : if ((test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1729 8 : (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
1730 12 : if (q.query_secdesc.out.sd->dacl == NULL ||
1731 8 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1732 8 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1733 4 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1734 8 : sd_orig->owner_sid) ||
1735 4 : q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1736 0 : torture_warning(tctx, "(CI & NP) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1737 0 : test_flags[i].dir_flags,
1738 0 : test_flags[i].parent_flags, i);
1739 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1740 0 : torture_comment(tctx, "FYI, here is the parent sd:\n");
1741 0 : NDR_PRINT_DEBUG(security_descriptor, sd);
1742 0 : ret = false;
1743 0 : continue;
1744 : }
1745 6 : } else if (test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
1746 8 : if (q.query_secdesc.out.sd->dacl == NULL ||
1747 8 : q.query_secdesc.out.sd->dacl->num_aces != 2 ||
1748 8 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1749 4 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1750 8 : sd_orig->owner_sid) ||
1751 8 : q.query_secdesc.out.sd->dacl->aces[1].access_mask != SEC_FILE_WRITE_DATA ||
1752 4 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[1].trustee,
1753 4 : creator_owner) ||
1754 8 : q.query_secdesc.out.sd->dacl->aces[0].flags != 0 ||
1755 4 : q.query_secdesc.out.sd->dacl->aces[1].flags !=
1756 4 : (test_flags[i].dir_flags | SEC_ACE_FLAG_INHERIT_ONLY)) {
1757 0 : torture_warning(tctx, "(CI) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1758 0 : test_flags[i].dir_flags,
1759 0 : test_flags[i].parent_flags, i);
1760 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1761 0 : torture_comment(tctx, "FYI, here is the parent sd:\n");
1762 0 : NDR_PRINT_DEBUG(security_descriptor, sd);
1763 0 : ret = false;
1764 0 : continue;
1765 : }
1766 : } else {
1767 4 : if (q.query_secdesc.out.sd->dacl == NULL ||
1768 4 : q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1769 4 : q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1770 2 : !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1771 2 : creator_owner) ||
1772 2 : q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1773 0 : torture_warning(tctx, "(0) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1774 0 : test_flags[i].dir_flags,
1775 0 : test_flags[i].parent_flags, i);
1776 0 : NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1777 0 : torture_comment(tctx, "FYI, here is the parent sd:\n");
1778 0 : NDR_PRINT_DEBUG(security_descriptor, sd);
1779 0 : ret = false;
1780 0 : continue;
1781 : }
1782 : }
1783 : }
1784 :
1785 1 : torture_comment(tctx, "Testing access checks on inherited create with %s\n", fname1);
1786 1 : sd = security_descriptor_dacl_create(tctx,
1787 : 0, NULL, NULL,
1788 : owner_sid,
1789 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1790 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1791 : SEC_ACE_FLAG_OBJECT_INHERIT,
1792 : SID_WORLD,
1793 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1794 : SEC_FILE_ALL | SEC_STD_ALL,
1795 : 0,
1796 : NULL);
1797 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1798 1 : set.set_secdesc.in.file.fnum = fnum;
1799 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1800 1 : set.set_secdesc.in.sd = sd;
1801 1 : status = smb_raw_setfileinfo(cli->tree, &set);
1802 1 : CHECK_STATUS(status, NT_STATUS_OK);
1803 :
1804 : /* Check DACL we just set. */
1805 1 : torture_comment(tctx, "checking new sd\n");
1806 1 : q.query_secdesc.in.file.fnum = fnum;
1807 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
1808 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1809 1 : CHECK_STATUS(status, NT_STATUS_OK);
1810 1 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
1811 :
1812 1 : io.ntcreatex.in.fname = fname1;
1813 1 : io.ntcreatex.in.create_options = 0;
1814 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1815 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1816 1 : status = smb_raw_open(cli->tree, tctx, &io);
1817 1 : CHECK_STATUS(status, NT_STATUS_OK);
1818 1 : fnum2 = io.ntcreatex.out.file.fnum;
1819 1 : CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1820 :
1821 1 : q.query_secdesc.in.file.fnum = fnum2;
1822 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1823 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
1824 1 : CHECK_STATUS(status, NT_STATUS_OK);
1825 1 : smbcli_close(cli->tree, fnum2);
1826 :
1827 1 : sd2 = security_descriptor_dacl_create(tctx,
1828 : 0, owner_sid, NULL,
1829 : owner_sid,
1830 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1831 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1832 : 0,
1833 : NULL);
1834 1 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1835 :
1836 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1837 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1838 1 : status = smb_raw_open(cli->tree, tctx, &io);
1839 1 : if (NT_STATUS_IS_OK(status)) {
1840 0 : torture_warning(tctx, "failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1841 0 : ret = false;
1842 0 : fnum2 = io.ntcreatex.out.file.fnum;
1843 0 : CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1844 0 : smbcli_close(cli->tree, fnum2);
1845 : } else {
1846 1 : if (TARGET_IS_WIN7(tctx)) {
1847 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1848 : } else {
1849 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1850 : }
1851 : }
1852 :
1853 1 : torture_comment(tctx, "trying without execute\n");
1854 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1855 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL & ~SEC_FILE_EXECUTE;
1856 1 : status = smb_raw_open(cli->tree, tctx, &io);
1857 1 : if (TARGET_IS_WIN7(tctx)) {
1858 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1859 : } else {
1860 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1861 : }
1862 :
1863 1 : torture_comment(tctx, "and with full permissions again\n");
1864 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1865 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1866 1 : status = smb_raw_open(cli->tree, tctx, &io);
1867 1 : if (TARGET_IS_WIN7(tctx)) {
1868 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1869 : } else {
1870 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1871 : }
1872 :
1873 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1874 1 : status = smb_raw_open(cli->tree, tctx, &io);
1875 1 : CHECK_STATUS(status, NT_STATUS_OK);
1876 1 : fnum2 = io.ntcreatex.out.file.fnum;
1877 1 : CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1878 1 : smbcli_close(cli->tree, fnum2);
1879 :
1880 1 : torture_comment(tctx, "put back original sd\n");
1881 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1882 1 : set.set_secdesc.in.file.fnum = fnum;
1883 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1884 1 : set.set_secdesc.in.sd = sd_orig;
1885 1 : status = smb_raw_setfileinfo(cli->tree, &set);
1886 1 : CHECK_STATUS(status, NT_STATUS_OK);
1887 :
1888 1 : smbcli_close(cli->tree, fnum);
1889 :
1890 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1891 1 : status = smb_raw_open(cli->tree, tctx, &io);
1892 1 : if (TARGET_IS_WIN7(tctx)) {
1893 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1894 : } else {
1895 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1896 : }
1897 :
1898 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1899 1 : status = smb_raw_open(cli->tree, tctx, &io);
1900 1 : CHECK_STATUS(status, NT_STATUS_OK);
1901 1 : fnum2 = io.ntcreatex.out.file.fnum;
1902 1 : CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1903 1 : smbcli_close(cli->tree, fnum2);
1904 :
1905 1 : done:
1906 1 : if (sd_orig != NULL) {
1907 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1908 1 : set.set_secdesc.in.file.fnum = fnum;
1909 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1910 1 : set.set_secdesc.in.sd = sd_orig;
1911 1 : status = smb_raw_setfileinfo(cli->tree, &set);
1912 : }
1913 :
1914 1 : smbcli_close(cli->tree, fnum);
1915 1 : smbcli_unlink(cli->tree, fname1);
1916 1 : smbcli_rmdir(cli->tree, dname);
1917 1 : smb_raw_exit(cli->session);
1918 1 : smbcli_deltree(cli->tree, BASEDIR);
1919 :
1920 1 : if (!ret) {
1921 0 : torture_result(tctx,
1922 : TORTURE_FAIL, "(%s) test_inheritance\n",
1923 : __location__);
1924 : }
1925 :
1926 1 : return ret;
1927 : }
1928 :
1929 1 : static bool test_inheritance_flags(struct torture_context *tctx,
1930 : struct smbcli_state *cli)
1931 : {
1932 : NTSTATUS status;
1933 : union smb_open io;
1934 1 : const char *dname = BASEDIR "\\inheritance";
1935 1 : const char *fname1 = BASEDIR "\\inheritance\\testfile";
1936 1 : bool ret = true;
1937 1 : int fnum=0, fnum2, i, j;
1938 : union smb_fileinfo q;
1939 : union smb_setfileinfo set;
1940 1 : struct security_descriptor *sd, *sd2, *sd_orig=NULL;
1941 : const char *owner_sid;
1942 : struct {
1943 : uint32_t parent_set_sd_type; /* 3 options */
1944 : uint32_t parent_set_ace_inherit; /* 1 option */
1945 : uint32_t parent_get_sd_type;
1946 : uint32_t parent_get_ace_inherit;
1947 : uint32_t child_get_sd_type;
1948 : uint32_t child_get_ace_inherit;
1949 1 : } tflags[16] = {{0}}; /* 2^4 */
1950 :
1951 16 : for (i = 0; i < 15; i++) {
1952 15 : torture_comment(tctx, "i=%d:", i);
1953 :
1954 15 : ZERO_STRUCT(tflags[i]);
1955 :
1956 15 : if (i & 1) {
1957 7 : tflags[i].parent_set_sd_type |=
1958 : SEC_DESC_DACL_AUTO_INHERITED;
1959 7 : torture_comment(tctx, "AUTO_INHERITED, ");
1960 : }
1961 15 : if (i & 2) {
1962 7 : tflags[i].parent_set_sd_type |=
1963 : SEC_DESC_DACL_AUTO_INHERIT_REQ;
1964 7 : torture_comment(tctx, "AUTO_INHERIT_REQ, ");
1965 : }
1966 15 : if (i & 4) {
1967 7 : tflags[i].parent_set_sd_type |=
1968 : SEC_DESC_DACL_PROTECTED;
1969 7 : tflags[i].parent_get_sd_type |=
1970 : SEC_DESC_DACL_PROTECTED;
1971 7 : torture_comment(tctx, "PROTECTED, ");
1972 : }
1973 15 : if (i & 8) {
1974 7 : tflags[i].parent_set_ace_inherit |=
1975 : SEC_ACE_FLAG_INHERITED_ACE;
1976 7 : tflags[i].parent_get_ace_inherit |=
1977 : SEC_ACE_FLAG_INHERITED_ACE;
1978 7 : torture_comment(tctx, "INHERITED, ");
1979 : }
1980 :
1981 15 : if ((tflags[i].parent_set_sd_type &
1982 : (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) ==
1983 : (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) {
1984 3 : tflags[i].parent_get_sd_type |=
1985 : SEC_DESC_DACL_AUTO_INHERITED;
1986 3 : tflags[i].child_get_sd_type |=
1987 : SEC_DESC_DACL_AUTO_INHERITED;
1988 3 : tflags[i].child_get_ace_inherit |=
1989 : SEC_ACE_FLAG_INHERITED_ACE;
1990 3 : torture_comment(tctx, " ... parent is AUTO INHERITED");
1991 : }
1992 :
1993 15 : if (tflags[i].parent_set_ace_inherit &
1994 : SEC_ACE_FLAG_INHERITED_ACE) {
1995 7 : tflags[i].parent_get_ace_inherit =
1996 : SEC_ACE_FLAG_INHERITED_ACE;
1997 7 : torture_comment(tctx, " ... parent ACE is INHERITED");
1998 : }
1999 :
2000 15 : torture_comment(tctx, "\n");
2001 : }
2002 :
2003 1 : if (!torture_setup_dir(cli, BASEDIR))
2004 0 : return false;
2005 :
2006 1 : torture_comment(tctx, "TESTING ACL INHERITANCE FLAGS\n");
2007 :
2008 1 : ZERO_STRUCT(io);
2009 :
2010 1 : io.generic.level = RAW_OPEN_NTCREATEX;
2011 1 : io.ntcreatex.in.root_fid.fnum = 0;
2012 1 : io.ntcreatex.in.flags = 0;
2013 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2014 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2015 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
2016 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
2017 1 : io.ntcreatex.in.alloc_size = 0;
2018 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2019 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2020 1 : io.ntcreatex.in.security_flags = 0;
2021 1 : io.ntcreatex.in.fname = dname;
2022 :
2023 1 : torture_comment(tctx, "creating initial directory %s\n", dname);
2024 1 : status = smb_raw_open(cli->tree, tctx, &io);
2025 1 : CHECK_STATUS(status, NT_STATUS_OK);
2026 1 : fnum = io.ntcreatex.out.file.fnum;
2027 :
2028 1 : torture_comment(tctx, "getting original sd\n");
2029 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2030 1 : q.query_secdesc.in.file.fnum = fnum;
2031 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2032 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
2033 1 : CHECK_STATUS(status, NT_STATUS_OK);
2034 1 : sd_orig = q.query_secdesc.out.sd;
2035 :
2036 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2037 1 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
2038 :
2039 17 : for (i=0; i < ARRAY_SIZE(tflags); i++) {
2040 16 : torture_comment(tctx, "setting a new sd on directory, pass #%d\n", i);
2041 :
2042 32 : sd = security_descriptor_dacl_create(tctx,
2043 16 : tflags[i].parent_set_sd_type,
2044 : NULL, NULL,
2045 : owner_sid,
2046 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2047 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
2048 : SEC_ACE_FLAG_OBJECT_INHERIT |
2049 : SEC_ACE_FLAG_CONTAINER_INHERIT |
2050 16 : tflags[i].parent_set_ace_inherit,
2051 : SID_WORLD,
2052 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2053 : SEC_FILE_ALL | SEC_STD_ALL,
2054 : 0,
2055 : NULL);
2056 16 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2057 16 : set.set_secdesc.in.file.fnum = fnum;
2058 16 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2059 16 : set.set_secdesc.in.sd = sd;
2060 16 : status = smb_raw_setfileinfo(cli->tree, &set);
2061 16 : CHECK_STATUS(status, NT_STATUS_OK);
2062 :
2063 : /*
2064 : * Check DACL we just set, except change the bits to what they
2065 : * should be.
2066 : */
2067 16 : torture_comment(tctx, " checking new sd\n");
2068 :
2069 : /* REQ bit should always be false. */
2070 16 : sd->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
2071 :
2072 16 : if ((tflags[i].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
2073 13 : sd->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
2074 :
2075 16 : q.query_secdesc.in.file.fnum = fnum;
2076 16 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
2077 16 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
2078 16 : CHECK_STATUS(status, NT_STATUS_OK);
2079 16 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
2080 :
2081 : /* Create file. */
2082 16 : torture_comment(tctx, " creating file %s\n", fname1);
2083 16 : io.ntcreatex.in.fname = fname1;
2084 16 : io.ntcreatex.in.create_options = 0;
2085 16 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2086 16 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2087 16 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2088 16 : status = smb_raw_open(cli->tree, tctx, &io);
2089 16 : CHECK_STATUS(status, NT_STATUS_OK);
2090 16 : fnum2 = io.ntcreatex.out.file.fnum;
2091 16 : CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
2092 :
2093 16 : q.query_secdesc.in.file.fnum = fnum2;
2094 16 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2095 16 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
2096 16 : CHECK_STATUS(status, NT_STATUS_OK);
2097 :
2098 16 : torture_comment(tctx, " checking sd on file %s\n", fname1);
2099 32 : sd2 = security_descriptor_dacl_create(tctx,
2100 16 : tflags[i].child_get_sd_type,
2101 : owner_sid, NULL,
2102 : owner_sid,
2103 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2104 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
2105 : tflags[i].child_get_ace_inherit,
2106 : NULL);
2107 16 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
2108 :
2109 : /*
2110 : * Set new sd on file ... prove that the bits have nothing to
2111 : * do with the parents bits when manually setting an ACL. The
2112 : * _AUTO_INHERITED bit comes directly from the ACL set.
2113 : */
2114 272 : for (j = 0; j < ARRAY_SIZE(tflags); j++) {
2115 256 : torture_comment(tctx, " setting new file sd, pass #%d\n", j);
2116 :
2117 : /* Change sd type. */
2118 256 : sd2->type &= ~(SEC_DESC_DACL_AUTO_INHERITED |
2119 : SEC_DESC_DACL_AUTO_INHERIT_REQ |
2120 : SEC_DESC_DACL_PROTECTED);
2121 256 : sd2->type |= tflags[j].parent_set_sd_type;
2122 :
2123 256 : sd2->dacl->aces[0].flags &=
2124 : ~SEC_ACE_FLAG_INHERITED_ACE;
2125 512 : sd2->dacl->aces[0].flags |=
2126 256 : tflags[j].parent_set_ace_inherit;
2127 :
2128 256 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2129 256 : set.set_secdesc.in.file.fnum = fnum2;
2130 256 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2131 256 : set.set_secdesc.in.sd = sd2;
2132 256 : status = smb_raw_setfileinfo(cli->tree, &set);
2133 256 : CHECK_STATUS(status, NT_STATUS_OK);
2134 :
2135 : /* Check DACL we just set. */
2136 256 : sd2->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
2137 256 : if ((tflags[j].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
2138 208 : sd2->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
2139 :
2140 256 : q.query_secdesc.in.file.fnum = fnum2;
2141 256 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2142 256 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
2143 256 : CHECK_STATUS(status, NT_STATUS_OK);
2144 :
2145 256 : CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
2146 : }
2147 :
2148 16 : smbcli_close(cli->tree, fnum2);
2149 16 : smbcli_unlink(cli->tree, fname1);
2150 : }
2151 :
2152 1 : done:
2153 1 : smbcli_close(cli->tree, fnum);
2154 1 : smb_raw_exit(cli->session);
2155 1 : smbcli_deltree(cli->tree, BASEDIR);
2156 :
2157 1 : if (!ret) {
2158 1 : torture_result(tctx,
2159 : TORTURE_FAIL, "(%s) test_inheritance_flags\n",
2160 : __location__);
2161 : }
2162 :
2163 1 : return ret;
2164 : }
2165 :
2166 : /*
2167 : test dynamic acl inheritance
2168 : Test copied to smb2/acls.c for SMB2.
2169 : */
2170 1 : static bool test_inheritance_dynamic(struct torture_context *tctx,
2171 : struct smbcli_state *cli)
2172 : {
2173 : NTSTATUS status;
2174 : union smb_open io;
2175 1 : const char *dname = BASEDIR "\\inheritance2";
2176 1 : const char *fname1 = BASEDIR "\\inheritance2\\testfile";
2177 1 : bool ret = true;
2178 1 : int fnum=0, fnum2;
2179 : union smb_fileinfo q;
2180 : union smb_setfileinfo set;
2181 1 : struct security_descriptor *sd, *sd_orig=NULL;
2182 : const char *owner_sid;
2183 :
2184 1 : torture_comment(tctx, "TESTING DYNAMIC ACL INHERITANCE\n");
2185 :
2186 1 : if (!torture_setup_dir(cli, BASEDIR))
2187 0 : return false;
2188 :
2189 1 : io.generic.level = RAW_OPEN_NTCREATEX;
2190 1 : io.ntcreatex.in.root_fid.fnum = 0;
2191 1 : io.ntcreatex.in.flags = 0;
2192 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2193 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2194 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
2195 1 : io.ntcreatex.in.share_access = 0;
2196 1 : io.ntcreatex.in.alloc_size = 0;
2197 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2198 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2199 1 : io.ntcreatex.in.security_flags = 0;
2200 1 : io.ntcreatex.in.fname = dname;
2201 :
2202 1 : status = smb_raw_open(cli->tree, tctx, &io);
2203 1 : CHECK_STATUS(status, NT_STATUS_OK);
2204 1 : fnum = io.ntcreatex.out.file.fnum;
2205 :
2206 1 : torture_comment(tctx, "get the original sd\n");
2207 1 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2208 1 : q.query_secdesc.in.file.fnum = fnum;
2209 1 : q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2210 1 : status = smb_raw_fileinfo(cli->tree, tctx, &q);
2211 1 : CHECK_STATUS(status, NT_STATUS_OK);
2212 1 : sd_orig = q.query_secdesc.out.sd;
2213 :
2214 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2215 :
2216 1 : torture_comment(tctx, "owner_sid is %s\n", owner_sid);
2217 :
2218 1 : sd = security_descriptor_dacl_create(tctx,
2219 : 0, NULL, NULL,
2220 : owner_sid,
2221 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2222 : SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE,
2223 : SEC_ACE_FLAG_OBJECT_INHERIT,
2224 : NULL);
2225 1 : sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
2226 :
2227 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2228 1 : set.set_secdesc.in.file.fnum = fnum;
2229 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2230 1 : set.set_secdesc.in.sd = sd;
2231 1 : status = smb_raw_setfileinfo(cli->tree, &set);
2232 1 : CHECK_STATUS(status, NT_STATUS_OK);
2233 :
2234 1 : torture_comment(tctx, "create a file with an inherited acl\n");
2235 1 : io.ntcreatex.in.fname = fname1;
2236 1 : io.ntcreatex.in.create_options = 0;
2237 1 : io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE;
2238 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2239 1 : status = smb_raw_open(cli->tree, tctx, &io);
2240 1 : CHECK_STATUS(status, NT_STATUS_OK);
2241 1 : fnum2 = io.ntcreatex.out.file.fnum;
2242 1 : smbcli_close(cli->tree, fnum2);
2243 :
2244 1 : torture_comment(tctx, "try and access file with base rights - should be OK\n");
2245 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
2246 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2247 1 : status = smb_raw_open(cli->tree, tctx, &io);
2248 1 : CHECK_STATUS(status, NT_STATUS_OK);
2249 1 : fnum2 = io.ntcreatex.out.file.fnum;
2250 1 : smbcli_close(cli->tree, fnum2);
2251 :
2252 1 : torture_comment(tctx, "try and access file with extra rights - should be denied\n");
2253 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
2254 1 : status = smb_raw_open(cli->tree, tctx, &io);
2255 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
2256 :
2257 1 : torture_comment(tctx, "update parent sd\n");
2258 1 : sd = security_descriptor_dacl_create(tctx,
2259 : 0, NULL, NULL,
2260 : owner_sid,
2261 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2262 : SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE,
2263 : SEC_ACE_FLAG_OBJECT_INHERIT,
2264 : NULL);
2265 1 : sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
2266 :
2267 1 : set.set_secdesc.in.sd = sd;
2268 1 : status = smb_raw_setfileinfo(cli->tree, &set);
2269 1 : CHECK_STATUS(status, NT_STATUS_OK);
2270 :
2271 1 : torture_comment(tctx, "try and access file with base rights - should be OK\n");
2272 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
2273 1 : status = smb_raw_open(cli->tree, tctx, &io);
2274 1 : CHECK_STATUS(status, NT_STATUS_OK);
2275 1 : fnum2 = io.ntcreatex.out.file.fnum;
2276 1 : smbcli_close(cli->tree, fnum2);
2277 :
2278 :
2279 1 : torture_comment(tctx, "try and access now - should be OK if dynamic inheritance works\n");
2280 1 : io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
2281 1 : status = smb_raw_open(cli->tree, tctx, &io);
2282 1 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2283 1 : torture_comment(tctx, "Server does not have dynamic inheritance\n");
2284 : }
2285 1 : if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
2286 0 : torture_comment(tctx, "Server does have dynamic inheritance\n");
2287 : }
2288 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
2289 :
2290 1 : smbcli_unlink(cli->tree, fname1);
2291 :
2292 1 : done:
2293 1 : if (sd_orig != NULL) {
2294 1 : torture_comment(tctx, "put back original sd\n");
2295 1 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2296 1 : set.set_secdesc.in.file.fnum = fnum;
2297 1 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2298 1 : set.set_secdesc.in.sd = sd_orig;
2299 1 : status = smb_raw_setfileinfo(cli->tree, &set);
2300 : }
2301 1 : smbcli_close(cli->tree, fnum);
2302 1 : smbcli_rmdir(cli->tree, dname);
2303 1 : smb_raw_exit(cli->session);
2304 1 : smbcli_deltree(cli->tree, BASEDIR);
2305 :
2306 1 : return ret;
2307 : }
2308 :
2309 : #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
2310 : if (!(bits & desired_64)) {\
2311 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
2312 : action; \
2313 : } else { \
2314 : CHECK_STATUS(status, NT_STATUS_OK); \
2315 : } \
2316 : } while (0)
2317 :
2318 : #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
2319 : if (NT_STATUS_IS_OK(status)) { \
2320 : if (!(granted & access)) {\
2321 : ret = false; \
2322 : torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
2323 : __location__, nt_errstr(status), access, granted, desired); \
2324 : goto done; \
2325 : } \
2326 : } else { \
2327 : if (granted & access) {\
2328 : ret = false; \
2329 : torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
2330 : __location__, nt_errstr(status), access, granted, desired); \
2331 : goto done; \
2332 : } \
2333 : } \
2334 : CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
2335 : } while (0)
2336 :
2337 : #if 0
2338 :
2339 : /* test what access mask is needed for getting and setting security_descriptors
2340 : Test copied to smb2/acls.c for SMB2. */
2341 : static bool test_sd_get_set(struct torture_context *tctx,
2342 : struct smbcli_state *cli)
2343 : {
2344 : NTSTATUS status;
2345 : bool ret = true;
2346 : union smb_open io;
2347 : union smb_fileinfo fi;
2348 : union smb_setfileinfo si;
2349 : struct security_descriptor *sd;
2350 : struct security_descriptor *sd_owner = NULL;
2351 : struct security_descriptor *sd_group = NULL;
2352 : struct security_descriptor *sd_dacl = NULL;
2353 : struct security_descriptor *sd_sacl = NULL;
2354 : int fnum=0;
2355 : const char *fname = BASEDIR "\\sd_get_set.txt";
2356 : uint64_t desired_64;
2357 : uint32_t desired = 0, granted;
2358 : int i = 0;
2359 : #define NO_BITS_HACK (((uint64_t)1)<<32)
2360 : uint64_t open_bits =
2361 : SEC_MASK_GENERIC |
2362 : SEC_FLAG_SYSTEM_SECURITY |
2363 : SEC_FLAG_MAXIMUM_ALLOWED |
2364 : SEC_STD_ALL |
2365 : SEC_FILE_ALL |
2366 : NO_BITS_HACK;
2367 : uint64_t get_owner_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
2368 : uint64_t set_owner_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
2369 : uint64_t get_group_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
2370 : uint64_t set_group_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
2371 : uint64_t get_dacl_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
2372 : uint64_t set_dacl_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_DAC;
2373 : uint64_t get_sacl_bits = SEC_FLAG_SYSTEM_SECURITY;
2374 : uint64_t set_sacl_bits = SEC_FLAG_SYSTEM_SECURITY;
2375 :
2376 : if (!torture_setup_dir(cli, BASEDIR))
2377 : return false;
2378 :
2379 : torture_comment(tctx, "TESTING ACCESS MASKS FOR SD GET/SET\n");
2380 :
2381 : /* first create a file with full access for everyone */
2382 : sd = security_descriptor_dacl_create(tctx,
2383 : 0, SID_NT_ANONYMOUS, SID_BUILTIN_USERS,
2384 : SID_WORLD,
2385 : SEC_ACE_TYPE_ACCESS_ALLOWED,
2386 : SEC_GENERIC_ALL,
2387 : 0,
2388 : NULL);
2389 : sd->type |= SEC_DESC_SACL_PRESENT;
2390 : sd->sacl = NULL;
2391 : io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
2392 : io.ntcreatex.in.root_fid.fnum = 0;
2393 : io.ntcreatex.in.flags = 0;
2394 : io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
2395 : io.ntcreatex.in.create_options = 0;
2396 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2397 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2398 : io.ntcreatex.in.alloc_size = 0;
2399 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2400 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2401 : io.ntcreatex.in.security_flags = 0;
2402 : io.ntcreatex.in.fname = fname;
2403 : io.ntcreatex.in.sec_desc = sd;
2404 : io.ntcreatex.in.ea_list = NULL;
2405 : status = smb_raw_open(cli->tree, tctx, &io);
2406 : CHECK_STATUS(status, NT_STATUS_OK);
2407 : fnum = io.ntcreatex.out.file.fnum;
2408 :
2409 : status = smbcli_close(cli->tree, fnum);
2410 : CHECK_STATUS(status, NT_STATUS_OK);
2411 :
2412 : /*
2413 : * now try each access_mask bit and no bit at all in a loop
2414 : * and see what's allowed
2415 : * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
2416 : */
2417 : for (i=0; i <= 32; i++) {
2418 : desired_64 = ((uint64_t)1) << i;
2419 : desired = (uint32_t)desired_64;
2420 :
2421 : /* first open the file with the desired access */
2422 : io.ntcreatex.level = RAW_OPEN_NTCREATEX;
2423 : io.ntcreatex.in.access_mask = desired;
2424 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2425 : status = smb_raw_open(cli->tree, tctx, &io);
2426 : CHECK_STATUS_FOR_BIT_ACTION(status, open_bits, goto next);
2427 : fnum = io.ntcreatex.out.file.fnum;
2428 :
2429 : /* then check what access was granted */
2430 : fi.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
2431 : fi.access_information.in.file.fnum = fnum;
2432 : status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2433 : CHECK_STATUS(status, NT_STATUS_OK);
2434 : granted = fi.access_information.out.access_flags;
2435 :
2436 : /* test the owner */
2437 : ZERO_STRUCT(fi);
2438 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2439 : fi.query_secdesc.in.file.fnum = fnum;
2440 : fi.query_secdesc.in.secinfo_flags = SECINFO_OWNER;
2441 : status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2442 : CHECK_STATUS_FOR_BIT(status, get_owner_bits, SEC_STD_READ_CONTROL);
2443 : if (fi.query_secdesc.out.sd) {
2444 : sd_owner = fi.query_secdesc.out.sd;
2445 : } else if (!sd_owner) {
2446 : sd_owner = sd;
2447 : }
2448 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2449 : si.set_secdesc.in.file.fnum = fnum;
2450 : si.set_secdesc.in.secinfo_flags = SECINFO_OWNER;
2451 : si.set_secdesc.in.sd = sd_owner;
2452 : status = smb_raw_setfileinfo(cli->tree, &si);
2453 : CHECK_STATUS_FOR_BIT(status, set_owner_bits, SEC_STD_WRITE_OWNER);
2454 :
2455 : /* test the group */
2456 : ZERO_STRUCT(fi);
2457 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2458 : fi.query_secdesc.in.file.fnum = fnum;
2459 : fi.query_secdesc.in.secinfo_flags = SECINFO_GROUP;
2460 : status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2461 : CHECK_STATUS_FOR_BIT(status, get_group_bits, SEC_STD_READ_CONTROL);
2462 : if (fi.query_secdesc.out.sd) {
2463 : sd_group = fi.query_secdesc.out.sd;
2464 : } else if (!sd_group) {
2465 : sd_group = sd;
2466 : }
2467 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2468 : si.set_secdesc.in.file.fnum = fnum;
2469 : si.set_secdesc.in.secinfo_flags = SECINFO_GROUP;
2470 : si.set_secdesc.in.sd = sd_group;
2471 : status = smb_raw_setfileinfo(cli->tree, &si);
2472 : CHECK_STATUS_FOR_BIT(status, set_group_bits, SEC_STD_WRITE_OWNER);
2473 :
2474 : /* test the DACL */
2475 : ZERO_STRUCT(fi);
2476 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2477 : fi.query_secdesc.in.file.fnum = fnum;
2478 : fi.query_secdesc.in.secinfo_flags = SECINFO_DACL;
2479 : status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2480 : CHECK_STATUS_FOR_BIT(status, get_dacl_bits, SEC_STD_READ_CONTROL);
2481 : if (fi.query_secdesc.out.sd) {
2482 : sd_dacl = fi.query_secdesc.out.sd;
2483 : } else if (!sd_dacl) {
2484 : sd_dacl = sd;
2485 : }
2486 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2487 : si.set_secdesc.in.file.fnum = fnum;
2488 : si.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2489 : si.set_secdesc.in.sd = sd_dacl;
2490 : status = smb_raw_setfileinfo(cli->tree, &si);
2491 : CHECK_STATUS_FOR_BIT(status, set_dacl_bits, SEC_STD_WRITE_DAC);
2492 :
2493 : /* test the SACL */
2494 : ZERO_STRUCT(fi);
2495 : fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2496 : fi.query_secdesc.in.file.fnum = fnum;
2497 : fi.query_secdesc.in.secinfo_flags = SECINFO_SACL;
2498 : status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2499 : CHECK_STATUS_FOR_BIT(status, get_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
2500 : if (fi.query_secdesc.out.sd) {
2501 : sd_sacl = fi.query_secdesc.out.sd;
2502 : } else if (!sd_sacl) {
2503 : sd_sacl = sd;
2504 : }
2505 : si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2506 : si.set_secdesc.in.file.fnum = fnum;
2507 : si.set_secdesc.in.secinfo_flags = SECINFO_SACL;
2508 : si.set_secdesc.in.sd = sd_sacl;
2509 : status = smb_raw_setfileinfo(cli->tree, &si);
2510 : CHECK_STATUS_FOR_BIT(status, set_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
2511 :
2512 : /* close the handle */
2513 : status = smbcli_close(cli->tree, fnum);
2514 : CHECK_STATUS(status, NT_STATUS_OK);
2515 : next:
2516 : continue;
2517 : }
2518 :
2519 : done:
2520 : smbcli_close(cli->tree, fnum);
2521 : smbcli_unlink(cli->tree, fname);
2522 : smb_raw_exit(cli->session);
2523 : smbcli_deltree(cli->tree, BASEDIR);
2524 :
2525 : return ret;
2526 : }
2527 :
2528 : #endif
2529 :
2530 : /*
2531 : basic testing of security descriptor calls
2532 : */
2533 964 : struct torture_suite *torture_raw_acls(TALLOC_CTX *mem_ctx)
2534 : {
2535 964 : struct torture_suite *suite = torture_suite_create(mem_ctx, "acls");
2536 :
2537 964 : torture_suite_add_1smb_test(suite, "sd", test_sd);
2538 964 : torture_suite_add_1smb_test(suite, "create_file", test_nttrans_create_file);
2539 964 : torture_suite_add_1smb_test(suite, "create_dir", test_nttrans_create_dir);
2540 964 : torture_suite_add_1smb_test(suite, "create_owner_file", test_nttrans_create_owner_file);
2541 964 : torture_suite_add_1smb_test(suite, "create_owner_dir", test_nttrans_create_owner_dir);
2542 964 : torture_suite_add_1smb_test(suite, "nulldacl", test_nttrans_create_null_dacl);
2543 964 : torture_suite_add_1smb_test(suite, "creator", test_creator_sid);
2544 964 : torture_suite_add_1smb_test(suite, "generic", test_generic_bits);
2545 964 : torture_suite_add_1smb_test(suite, "owner", test_owner_bits);
2546 964 : torture_suite_add_1smb_test(suite, "inheritance", test_inheritance);
2547 :
2548 964 : torture_suite_add_1smb_test(suite, "INHERITFLAGS", test_inheritance_flags);
2549 964 : torture_suite_add_1smb_test(suite, "dynamic", test_inheritance_dynamic);
2550 : #if 0
2551 : /* XXX This test does not work against XP or Vista. */
2552 : torture_suite_add_1smb_test(suite, "GETSET", test_sd_get_set);
2553 : #endif
2554 :
2555 964 : return suite;
2556 : }
|