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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/libcli.h"
27 #include "librpc/gen_ndr/lsa.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 
33 #define BASEDIR "\\testsd"
34 
35 #define CHECK_STATUS(status, correct) do { \
36 	if (!NT_STATUS_EQUAL(status, correct)) { \
37 		printf("(%s) Incorrect status %s - should be %s\n", \
38 		       __location__, nt_errstr(status), nt_errstr(correct)); \
39 		ret = False; \
40 		goto done; \
41 	}} while (0)
42 
43 
test_sd(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)44 static BOOL test_sd(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
45 {
46 	NTSTATUS status;
47 	union smb_open io;
48 	const char *fname = BASEDIR "\\sd.txt";
49 	BOOL ret = True;
50 	int fnum = -1;
51 	union smb_fileinfo q;
52 	union smb_setfileinfo set;
53 	struct security_ace ace;
54 	struct security_descriptor *sd;
55 	struct dom_sid *test_sid;
56 
57 	printf("TESTING SETFILEINFO EA_SET\n");
58 
59 	io.generic.level = RAW_OPEN_NTCREATEX;
60 	io.ntcreatex.in.root_fid = 0;
61 	io.ntcreatex.in.flags = 0;
62 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
63 	io.ntcreatex.in.create_options = 0;
64 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
65 	io.ntcreatex.in.share_access =
66 		NTCREATEX_SHARE_ACCESS_READ |
67 		NTCREATEX_SHARE_ACCESS_WRITE;
68 	io.ntcreatex.in.alloc_size = 0;
69 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
70 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
71 	io.ntcreatex.in.security_flags = 0;
72 	io.ntcreatex.in.fname = fname;
73 	status = smb_raw_open(cli->tree, mem_ctx, &io);
74 	CHECK_STATUS(status, NT_STATUS_OK);
75 	fnum = io.ntcreatex.out.file.fnum;
76 
77 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
78 	q.query_secdesc.in.file.fnum = fnum;
79 	q.query_secdesc.in.secinfo_flags =
80 		SECINFO_OWNER |
81 		SECINFO_GROUP |
82 		SECINFO_DACL;
83 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
84 	CHECK_STATUS(status, NT_STATUS_OK);
85 	sd = q.query_secdesc.out.sd;
86 
87 	printf("add a new ACE to the DACL\n");
88 
89 	test_sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1234-5432");
90 
91 	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
92 	ace.flags = 0;
93 	ace.access_mask = SEC_STD_ALL;
94 	ace.trustee = *test_sid;
95 
96 	status = security_descriptor_dacl_add(sd, &ace);
97 	CHECK_STATUS(status, NT_STATUS_OK);
98 
99 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
100 	set.set_secdesc.in.file.fnum = fnum;
101 	set.set_secdesc.in.secinfo_flags = q.query_secdesc.in.secinfo_flags;
102 	set.set_secdesc.in.sd = sd;
103 
104 	status = smb_raw_setfileinfo(cli->tree, &set);
105 	CHECK_STATUS(status, NT_STATUS_OK);
106 
107 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
108 	CHECK_STATUS(status, NT_STATUS_OK);
109 
110 	if (!security_acl_equal(q.query_secdesc.out.sd->dacl, sd->dacl)) {
111 		printf("%s: security descriptors don't match!\n", __location__);
112 		printf("got:\n");
113 		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
114 		printf("expected:\n");
115 		NDR_PRINT_DEBUG(security_descriptor, sd);
116 		ret = False;
117 	}
118 
119 	printf("remove it again\n");
120 
121 	status = security_descriptor_dacl_del(sd, test_sid);
122 	CHECK_STATUS(status, NT_STATUS_OK);
123 
124 	status = smb_raw_setfileinfo(cli->tree, &set);
125 	CHECK_STATUS(status, NT_STATUS_OK);
126 
127 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
128 	CHECK_STATUS(status, NT_STATUS_OK);
129 
130 	if (!security_acl_equal(q.query_secdesc.out.sd->dacl, sd->dacl)) {
131 		printf("%s: security descriptors don't match!\n", __location__);
132 		printf("got:\n");
133 		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
134 		printf("expected:\n");
135 		NDR_PRINT_DEBUG(security_descriptor, sd);
136 		ret = False;
137 	}
138 
139 done:
140 	smbcli_close(cli->tree, fnum);
141 	return ret;
142 }
143 
144 
145 /*
146   test using NTTRANS CREATE to create a file with an initial ACL set
147 */
test_nttrans_create(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)148 static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
149 {
150 	NTSTATUS status;
151 	union smb_open io;
152 	const char *fname = BASEDIR "\\acl2.txt";
153 	BOOL ret = True;
154 	int fnum = -1;
155 	union smb_fileinfo q;
156 	struct security_ace ace;
157 	struct security_descriptor *sd;
158 	struct dom_sid *test_sid;
159 
160 	printf("TESTING NTTRANS CREATE WITH SEC_DESC\n");
161 
162 	io.generic.level = RAW_OPEN_NTTRANS_CREATE;
163 	io.ntcreatex.in.root_fid = 0;
164 	io.ntcreatex.in.flags = 0;
165 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
166 	io.ntcreatex.in.create_options = 0;
167 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
168 	io.ntcreatex.in.share_access =
169 		NTCREATEX_SHARE_ACCESS_READ |
170 		NTCREATEX_SHARE_ACCESS_WRITE;
171 	io.ntcreatex.in.alloc_size = 0;
172 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
173 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
174 	io.ntcreatex.in.security_flags = 0;
175 	io.ntcreatex.in.fname = fname;
176 	io.ntcreatex.in.sec_desc = NULL;
177 	io.ntcreatex.in.ea_list = NULL;
178 
179 	printf("creating normal file\n");
180 
181 	status = smb_raw_open(cli->tree, mem_ctx, &io);
182 	CHECK_STATUS(status, NT_STATUS_OK);
183 	fnum = io.ntcreatex.out.file.fnum;
184 
185 	printf("querying ACL\n");
186 
187 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
188 	q.query_secdesc.in.file.fnum = fnum;
189 	q.query_secdesc.in.secinfo_flags =
190 		SECINFO_OWNER |
191 		SECINFO_GROUP |
192 		SECINFO_DACL;
193 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
194 	CHECK_STATUS(status, NT_STATUS_OK);
195 	sd = q.query_secdesc.out.sd;
196 
197 	smbcli_close(cli->tree, fnum);
198 	smbcli_unlink(cli->tree, fname);
199 
200 	printf("adding a new ACE\n");
201 	test_sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1234-54321");
202 
203 	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
204 	ace.flags = 0;
205 	ace.access_mask = SEC_STD_ALL;
206 	ace.trustee = *test_sid;
207 
208 	status = security_descriptor_dacl_add(sd, &ace);
209 	CHECK_STATUS(status, NT_STATUS_OK);
210 
211 	printf("creating a file with an initial ACL\n");
212 
213 	io.ntcreatex.in.sec_desc = sd;
214 	status = smb_raw_open(cli->tree, mem_ctx, &io);
215 	CHECK_STATUS(status, NT_STATUS_OK);
216 	fnum = io.ntcreatex.out.file.fnum;
217 
218 	q.query_secdesc.in.file.fnum = fnum;
219 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
220 	CHECK_STATUS(status, NT_STATUS_OK);
221 
222 	if (!security_acl_equal(q.query_secdesc.out.sd->dacl, sd->dacl)) {
223 		printf("%s: security descriptors don't match!\n", __location__);
224 		printf("got:\n");
225 		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
226 		printf("expected:\n");
227 		NDR_PRINT_DEBUG(security_descriptor, sd);
228 		ret = False;
229 	}
230 
231 done:
232 	smbcli_close(cli->tree, fnum);
233 	return ret;
234 }
235 
236 #define CHECK_ACCESS_FLAGS(_fnum, flags) do { \
237 	union smb_fileinfo _q; \
238 	_q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
239 	_q.access_information.in.file.fnum = (_fnum); \
240 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &_q); \
241 	CHECK_STATUS(status, NT_STATUS_OK); \
242 	if (_q.access_information.out.access_flags != (flags)) { \
243 		printf("(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
244 		       __location__, _q.access_information.out.access_flags, (flags)); \
245 		ret = False; \
246 		goto done; \
247 	} \
248 } while (0)
249 
250 
251 /*
252   test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
253   mapping bits
254 */
test_creator_sid(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)255 static BOOL test_creator_sid(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
256 {
257 	NTSTATUS status;
258 	union smb_open io;
259 	const char *fname = BASEDIR "\\creator.txt";
260 	BOOL ret = True;
261 	int fnum = -1;
262 	union smb_fileinfo q;
263 	union smb_setfileinfo set;
264 	struct security_descriptor *sd, *sd_orig, *sd2;
265 	const char *owner_sid;
266 
267 	printf("TESTING SID_CREATOR_OWNER\n");
268 
269 	io.generic.level = RAW_OPEN_NTCREATEX;
270 	io.ntcreatex.in.root_fid = 0;
271 	io.ntcreatex.in.flags = 0;
272 	io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER;
273 	io.ntcreatex.in.create_options = 0;
274 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
275 	io.ntcreatex.in.share_access =
276 		NTCREATEX_SHARE_ACCESS_READ |
277 		NTCREATEX_SHARE_ACCESS_WRITE;
278 	io.ntcreatex.in.alloc_size = 0;
279 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
280 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
281 	io.ntcreatex.in.security_flags = 0;
282 	io.ntcreatex.in.fname = fname;
283 	status = smb_raw_open(cli->tree, mem_ctx, &io);
284 	CHECK_STATUS(status, NT_STATUS_OK);
285 	fnum = io.ntcreatex.out.file.fnum;
286 
287 	printf("get the original sd\n");
288 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
289 	q.query_secdesc.in.file.fnum = fnum;
290 	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
291 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
292 	CHECK_STATUS(status, NT_STATUS_OK);
293 	sd_orig = q.query_secdesc.out.sd;
294 
295 	owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
296 
297 	printf("set a sec desc allowing no write by CREATOR_OWNER\n");
298 	sd = security_descriptor_create(mem_ctx,
299 					NULL, NULL,
300 					SID_CREATOR_OWNER,
301 					SEC_ACE_TYPE_ACCESS_ALLOWED,
302 					SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
303 					0,
304 					NULL);
305 
306 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
307 	set.set_secdesc.in.file.fnum = fnum;
308 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
309 	set.set_secdesc.in.sd = sd;
310 
311 	status = smb_raw_setfileinfo(cli->tree, &set);
312 	CHECK_STATUS(status, NT_STATUS_OK);
313 
314 	printf("try open for write\n");
315 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
316 	status = smb_raw_open(cli->tree, mem_ctx, &io);
317 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
318 
319 	printf("try open for read\n");
320 	io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
321 	status = smb_raw_open(cli->tree, mem_ctx, &io);
322 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
323 
324 	printf("try open for generic write\n");
325 	io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
326 	status = smb_raw_open(cli->tree, mem_ctx, &io);
327 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
328 
329 	printf("try open for generic read\n");
330 	io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
331 	status = smb_raw_open(cli->tree, mem_ctx, &io);
332 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
333 
334 	printf("set a sec desc allowing no write by owner\n");
335 	sd = security_descriptor_create(mem_ctx,
336 					owner_sid, NULL,
337 					owner_sid,
338 					SEC_ACE_TYPE_ACCESS_ALLOWED,
339 					SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
340 					0,
341 					NULL);
342 
343 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
344 	set.set_secdesc.in.file.fnum = fnum;
345 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
346 	set.set_secdesc.in.sd = sd;
347 	status = smb_raw_setfileinfo(cli->tree, &set);
348 	CHECK_STATUS(status, NT_STATUS_OK);
349 
350 	printf("check that sd has been mapped correctly\n");
351 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
352 	CHECK_STATUS(status, NT_STATUS_OK);
353 	if (!security_descriptor_equal(q.query_secdesc.out.sd, sd)) {
354 		printf("%s: security descriptors don't match!\n", __location__);
355 		printf("got:\n");
356 		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
357 		printf("expected:\n");
358 		NDR_PRINT_DEBUG(security_descriptor, sd);
359 		ret = False;
360 	}
361 
362 	printf("try open for write\n");
363 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
364 	status = smb_raw_open(cli->tree, mem_ctx, &io);
365 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
366 
367 	printf("try open for read\n");
368 	io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
369 	status = smb_raw_open(cli->tree, mem_ctx, &io);
370 	CHECK_STATUS(status, NT_STATUS_OK);
371 	CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
372 			   SEC_FILE_READ_DATA|
373 			   SEC_FILE_READ_ATTRIBUTE);
374 	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
375 
376 	printf("try open for generic write\n");
377 	io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
378 	status = smb_raw_open(cli->tree, mem_ctx, &io);
379 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
380 
381 	printf("try open for generic read\n");
382 	io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
383 	status = smb_raw_open(cli->tree, mem_ctx, &io);
384 	CHECK_STATUS(status, NT_STATUS_OK);
385 	CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
386 			   SEC_RIGHTS_FILE_READ);
387 	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
388 
389 	printf("set a sec desc allowing generic read by owner\n");
390 	sd = security_descriptor_create(mem_ctx,
391 					NULL, NULL,
392 					owner_sid,
393 					SEC_ACE_TYPE_ACCESS_ALLOWED,
394 					SEC_GENERIC_READ | SEC_STD_ALL,
395 					0,
396 					NULL);
397 
398 	set.set_secdesc.in.sd = sd;
399 	status = smb_raw_setfileinfo(cli->tree, &set);
400 	CHECK_STATUS(status, NT_STATUS_OK);
401 
402 	printf("check that generic read has been mapped correctly\n");
403 	sd2 = security_descriptor_create(mem_ctx,
404 					 owner_sid, NULL,
405 					 owner_sid,
406 					 SEC_ACE_TYPE_ACCESS_ALLOWED,
407 					 SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
408 					 0,
409 					 NULL);
410 
411 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
412 	CHECK_STATUS(status, NT_STATUS_OK);
413 	if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
414 		printf("%s: security descriptors don't match!\n", __location__);
415 		printf("got:\n");
416 		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
417 		printf("expected:\n");
418 		NDR_PRINT_DEBUG(security_descriptor, sd2);
419 		ret = False;
420 	}
421 
422 
423 	printf("try open for write\n");
424 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
425 	status = smb_raw_open(cli->tree, mem_ctx, &io);
426 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
427 
428 	printf("try open for read\n");
429 	io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
430 	status = smb_raw_open(cli->tree, mem_ctx, &io);
431 	CHECK_STATUS(status, NT_STATUS_OK);
432 	CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
433 			   SEC_FILE_READ_DATA |
434 			   SEC_FILE_READ_ATTRIBUTE);
435 	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
436 
437 	printf("try open for generic write\n");
438 	io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
439 	status = smb_raw_open(cli->tree, mem_ctx, &io);
440 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
441 
442 	printf("try open for generic read\n");
443 	io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
444 	status = smb_raw_open(cli->tree, mem_ctx, &io);
445 	CHECK_STATUS(status, NT_STATUS_OK);
446 	CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, SEC_RIGHTS_FILE_READ);
447 	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
448 
449 
450 	printf("put back original sd\n");
451 	set.set_secdesc.in.sd = sd_orig;
452 	status = smb_raw_setfileinfo(cli->tree, &set);
453 	CHECK_STATUS(status, NT_STATUS_OK);
454 
455 
456 done:
457 	smbcli_close(cli->tree, fnum);
458 	return ret;
459 }
460 
461 
462 /*
463   test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
464   SEC_FILE_xx bits
465 */
test_generic_bits(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)466 static BOOL test_generic_bits(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
467 {
468 	NTSTATUS status;
469 	union smb_open io;
470 	const char *fname = BASEDIR "\\generic.txt";
471 	BOOL ret = True;
472 	int fnum = -1, i;
473 	union smb_fileinfo q;
474 	union smb_setfileinfo set;
475 	struct security_descriptor *sd, *sd_orig, *sd2;
476 	const char *owner_sid;
477 	const struct {
478 		uint32_t gen_bits;
479 		uint32_t specific_bits;
480 	} file_mappings[] = {
481 		{ 0,                       0 },
482 		{ SEC_GENERIC_READ,        SEC_RIGHTS_FILE_READ },
483 		{ SEC_GENERIC_WRITE,       SEC_RIGHTS_FILE_WRITE },
484 		{ SEC_GENERIC_EXECUTE,     SEC_RIGHTS_FILE_EXECUTE },
485 		{ SEC_GENERIC_ALL,         SEC_RIGHTS_FILE_ALL },
486 		{ SEC_FILE_READ_DATA,      SEC_FILE_READ_DATA },
487 		{ SEC_FILE_READ_ATTRIBUTE, SEC_FILE_READ_ATTRIBUTE }
488 	};
489 	const struct {
490 		uint32_t gen_bits;
491 		uint32_t specific_bits;
492 	} dir_mappings[] = {
493 		{ 0,                   0 },
494 		{ SEC_GENERIC_READ,    SEC_RIGHTS_DIR_READ },
495 		{ SEC_GENERIC_WRITE,   SEC_RIGHTS_DIR_WRITE },
496 		{ SEC_GENERIC_EXECUTE, SEC_RIGHTS_DIR_EXECUTE },
497 		{ SEC_GENERIC_ALL,     SEC_RIGHTS_DIR_ALL }
498 	};
499 	BOOL has_restore_privilege;
500 	BOOL has_take_ownership_privilege;
501 
502 	printf("TESTING FILE GENERIC BITS\n");
503 
504 	io.generic.level = RAW_OPEN_NTCREATEX;
505 	io.ntcreatex.in.root_fid = 0;
506 	io.ntcreatex.in.flags = 0;
507 	io.ntcreatex.in.access_mask =
508 		SEC_STD_READ_CONTROL |
509 		SEC_STD_WRITE_DAC |
510 		SEC_STD_WRITE_OWNER;
511 	io.ntcreatex.in.create_options = 0;
512 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
513 	io.ntcreatex.in.share_access =
514 		NTCREATEX_SHARE_ACCESS_READ |
515 		NTCREATEX_SHARE_ACCESS_WRITE;
516 	io.ntcreatex.in.alloc_size = 0;
517 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
518 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
519 	io.ntcreatex.in.security_flags = 0;
520 	io.ntcreatex.in.fname = fname;
521 	status = smb_raw_open(cli->tree, mem_ctx, &io);
522 	CHECK_STATUS(status, NT_STATUS_OK);
523 	fnum = io.ntcreatex.out.file.fnum;
524 
525 	printf("get the original sd\n");
526 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
527 	q.query_secdesc.in.file.fnum = fnum;
528 	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
529 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
530 	CHECK_STATUS(status, NT_STATUS_OK);
531 	sd_orig = q.query_secdesc.out.sd;
532 
533 	owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
534 
535 	status = smblsa_sid_check_privilege(cli,
536 					    owner_sid,
537 					    sec_privilege_name(SEC_PRIV_RESTORE));
538 	has_restore_privilege = NT_STATUS_IS_OK(status);
539 	if (!NT_STATUS_IS_OK(status)) {
540 		printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
541 	}
542 	printf("SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
543 
544 	status = smblsa_sid_check_privilege(cli,
545 					    owner_sid,
546 					    sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
547 	has_take_ownership_privilege = NT_STATUS_IS_OK(status);
548 	if (!NT_STATUS_IS_OK(status)) {
549 		printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
550 	}
551 	printf("SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
552 
553 	for (i=0;i<ARRAY_SIZE(file_mappings);i++) {
554 		uint32_t expected_mask =
555 			SEC_STD_WRITE_DAC |
556 			SEC_STD_READ_CONTROL |
557 			SEC_FILE_READ_ATTRIBUTE |
558 			SEC_STD_DELETE;
559 		uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
560 
561 		if (has_restore_privilege) {
562 			expected_mask_anon |= SEC_STD_DELETE;
563 		}
564 
565 		printf("testing generic bits 0x%08x\n",
566 		       file_mappings[i].gen_bits);
567 		sd = security_descriptor_create(mem_ctx,
568 						owner_sid, NULL,
569 						owner_sid,
570 						SEC_ACE_TYPE_ACCESS_ALLOWED,
571 						file_mappings[i].gen_bits,
572 						0,
573 						NULL);
574 
575 		set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
576 		set.set_secdesc.in.file.fnum = fnum;
577 		set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
578 		set.set_secdesc.in.sd = sd;
579 
580 		status = smb_raw_setfileinfo(cli->tree, &set);
581 		CHECK_STATUS(status, NT_STATUS_OK);
582 
583 		sd2 = security_descriptor_create(mem_ctx,
584 						 owner_sid, NULL,
585 						 owner_sid,
586 						 SEC_ACE_TYPE_ACCESS_ALLOWED,
587 						 file_mappings[i].specific_bits,
588 						 0,
589 						 NULL);
590 
591 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
592 		CHECK_STATUS(status, NT_STATUS_OK);
593 		if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
594 			printf("%s: security descriptors don't match!\n", __location__);
595 			printf("got:\n");
596 			NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
597 			printf("expected:\n");
598 			NDR_PRINT_DEBUG(security_descriptor, sd2);
599 			ret = False;
600 		}
601 
602 		io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
603 		status = smb_raw_open(cli->tree, mem_ctx, &io);
604 		CHECK_STATUS(status, NT_STATUS_OK);
605 		CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
606 				   expected_mask | file_mappings[i].specific_bits);
607 		smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
608 
609 		if (!has_take_ownership_privilege) {
610 			continue;
611 		}
612 
613 		printf("testing generic bits 0x%08x (anonymous)\n",
614 		       file_mappings[i].gen_bits);
615 		sd = security_descriptor_create(mem_ctx,
616 						SID_NT_ANONYMOUS, NULL,
617 						owner_sid,
618 						SEC_ACE_TYPE_ACCESS_ALLOWED,
619 						file_mappings[i].gen_bits,
620 						0,
621 						NULL);
622 
623 		set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
624 		set.set_secdesc.in.file.fnum = fnum;
625 		set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
626 		set.set_secdesc.in.sd = sd;
627 
628 		status = smb_raw_setfileinfo(cli->tree, &set);
629 		CHECK_STATUS(status, NT_STATUS_OK);
630 
631 		sd2 = security_descriptor_create(mem_ctx,
632 						 SID_NT_ANONYMOUS, NULL,
633 						 owner_sid,
634 						 SEC_ACE_TYPE_ACCESS_ALLOWED,
635 						 file_mappings[i].specific_bits,
636 						 0,
637 						 NULL);
638 
639 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
640 		CHECK_STATUS(status, NT_STATUS_OK);
641 		if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
642 			printf("%s: security descriptors don't match!\n", __location__);
643 			printf("got:\n");
644 			NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
645 			printf("expected:\n");
646 			NDR_PRINT_DEBUG(security_descriptor, sd2);
647 			ret = False;
648 		}
649 
650 		io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
651 		status = smb_raw_open(cli->tree, mem_ctx, &io);
652 		CHECK_STATUS(status, NT_STATUS_OK);
653 		CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
654 				   expected_mask_anon | file_mappings[i].specific_bits);
655 		smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
656 	}
657 
658 	printf("put back original sd\n");
659 	set.set_secdesc.in.sd = sd_orig;
660 	status = smb_raw_setfileinfo(cli->tree, &set);
661 	CHECK_STATUS(status, NT_STATUS_OK);
662 
663 	smbcli_close(cli->tree, fnum);
664 	smbcli_unlink(cli->tree, fname);
665 
666 
667 	printf("TESTING DIR GENERIC BITS\n");
668 
669 	io.generic.level = RAW_OPEN_NTCREATEX;
670 	io.ntcreatex.in.root_fid = 0;
671 	io.ntcreatex.in.flags = 0;
672 	io.ntcreatex.in.access_mask =
673 		SEC_STD_READ_CONTROL |
674 		SEC_STD_WRITE_DAC |
675 		SEC_STD_WRITE_OWNER;
676 	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
677 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
678 	io.ntcreatex.in.share_access =
679 		NTCREATEX_SHARE_ACCESS_READ |
680 		NTCREATEX_SHARE_ACCESS_WRITE;
681 	io.ntcreatex.in.alloc_size = 0;
682 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
683 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
684 	io.ntcreatex.in.security_flags = 0;
685 	io.ntcreatex.in.fname = fname;
686 	status = smb_raw_open(cli->tree, mem_ctx, &io);
687 	CHECK_STATUS(status, NT_STATUS_OK);
688 	fnum = io.ntcreatex.out.file.fnum;
689 
690 	printf("get the original sd\n");
691 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
692 	q.query_secdesc.in.file.fnum = fnum;
693 	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
694 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
695 	CHECK_STATUS(status, NT_STATUS_OK);
696 	sd_orig = q.query_secdesc.out.sd;
697 
698 	owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
699 
700 	status = smblsa_sid_check_privilege(cli,
701 					    owner_sid,
702 					    sec_privilege_name(SEC_PRIV_RESTORE));
703 	has_restore_privilege = NT_STATUS_IS_OK(status);
704 	if (!NT_STATUS_IS_OK(status)) {
705 		printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
706 	}
707 	printf("SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
708 
709 	status = smblsa_sid_check_privilege(cli,
710 					    owner_sid,
711 					    sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
712 	has_take_ownership_privilege = NT_STATUS_IS_OK(status);
713 	if (!NT_STATUS_IS_OK(status)) {
714 		printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
715 	}
716 	printf("SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
717 
718 	for (i=0;i<ARRAY_SIZE(dir_mappings);i++) {
719 		uint32_t expected_mask =
720 			SEC_STD_WRITE_DAC |
721 			SEC_STD_READ_CONTROL |
722 			SEC_FILE_READ_ATTRIBUTE |
723 			SEC_STD_DELETE;
724 		uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
725 
726 		if (has_restore_privilege) {
727 			expected_mask_anon |= SEC_STD_DELETE;
728 		}
729 
730 		printf("testing generic bits 0x%08x\n",
731 		       file_mappings[i].gen_bits);
732 		sd = security_descriptor_create(mem_ctx,
733 						owner_sid, NULL,
734 						owner_sid,
735 						SEC_ACE_TYPE_ACCESS_ALLOWED,
736 						dir_mappings[i].gen_bits,
737 						0,
738 						NULL);
739 
740 		set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
741 		set.set_secdesc.in.file.fnum = fnum;
742 		set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
743 		set.set_secdesc.in.sd = sd;
744 
745 		status = smb_raw_setfileinfo(cli->tree, &set);
746 		CHECK_STATUS(status, NT_STATUS_OK);
747 
748 		sd2 = security_descriptor_create(mem_ctx,
749 						 owner_sid, NULL,
750 						 owner_sid,
751 						 SEC_ACE_TYPE_ACCESS_ALLOWED,
752 						 dir_mappings[i].specific_bits,
753 						 0,
754 						 NULL);
755 
756 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
757 		CHECK_STATUS(status, NT_STATUS_OK);
758 		if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
759 			printf("%s: security descriptors don't match!\n", __location__);
760 			printf("got:\n");
761 			NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
762 			printf("expected:\n");
763 			NDR_PRINT_DEBUG(security_descriptor, sd2);
764 			ret = False;
765 		}
766 
767 		io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
768 		status = smb_raw_open(cli->tree, mem_ctx, &io);
769 		CHECK_STATUS(status, NT_STATUS_OK);
770 		CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
771 				   expected_mask | dir_mappings[i].specific_bits);
772 		smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
773 
774 		if (!has_take_ownership_privilege) {
775 			continue;
776 		}
777 
778 		printf("testing generic bits 0x%08x (anonymous)\n",
779 		       file_mappings[i].gen_bits);
780 		sd = security_descriptor_create(mem_ctx,
781 						SID_NT_ANONYMOUS, NULL,
782 						owner_sid,
783 						SEC_ACE_TYPE_ACCESS_ALLOWED,
784 						file_mappings[i].gen_bits,
785 						0,
786 						NULL);
787 
788 		set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
789 		set.set_secdesc.in.file.fnum = fnum;
790 		set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
791 		set.set_secdesc.in.sd = sd;
792 
793 		status = smb_raw_setfileinfo(cli->tree, &set);
794 		CHECK_STATUS(status, NT_STATUS_OK);
795 
796 		sd2 = security_descriptor_create(mem_ctx,
797 						 SID_NT_ANONYMOUS, NULL,
798 						 owner_sid,
799 						 SEC_ACE_TYPE_ACCESS_ALLOWED,
800 						 file_mappings[i].specific_bits,
801 						 0,
802 						 NULL);
803 
804 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
805 		CHECK_STATUS(status, NT_STATUS_OK);
806 		if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
807 			printf("%s: security descriptors don't match!\n", __location__);
808 			printf("got:\n");
809 			NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
810 			printf("expected:\n");
811 			NDR_PRINT_DEBUG(security_descriptor, sd2);
812 			ret = False;
813 		}
814 
815 		io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
816 		status = smb_raw_open(cli->tree, mem_ctx, &io);
817 		CHECK_STATUS(status, NT_STATUS_OK);
818 		CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
819 				   expected_mask_anon | dir_mappings[i].specific_bits);
820 		smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
821 	}
822 
823 	printf("put back original sd\n");
824 	set.set_secdesc.in.sd = sd_orig;
825 	status = smb_raw_setfileinfo(cli->tree, &set);
826 	CHECK_STATUS(status, NT_STATUS_OK);
827 
828 	smbcli_close(cli->tree, fnum);
829 	smbcli_unlink(cli->tree, fname);
830 
831 done:
832 	smbcli_close(cli->tree, fnum);
833 	return ret;
834 }
835 
836 
837 /*
838   see what access bits the owner of a file always gets
839 */
test_owner_bits(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)840 static BOOL test_owner_bits(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
841 {
842 	NTSTATUS status;
843 	union smb_open io;
844 	const char *fname = BASEDIR "\\generic.txt";
845 	BOOL ret = True;
846 	int fnum = -1, i;
847 	union smb_fileinfo q;
848 	union smb_setfileinfo set;
849 	struct security_descriptor *sd, *sd_orig;
850 	const char *owner_sid;
851 	BOOL has_restore_privilege;
852 	BOOL has_take_ownership_privilege;
853 	uint32_t expected_bits;
854 
855 	printf("TESTING FILE OWNER BITS\n");
856 
857 	io.generic.level = RAW_OPEN_NTCREATEX;
858 	io.ntcreatex.in.root_fid = 0;
859 	io.ntcreatex.in.flags = 0;
860 	io.ntcreatex.in.access_mask =
861 		SEC_STD_READ_CONTROL |
862 		SEC_STD_WRITE_DAC |
863 		SEC_STD_WRITE_OWNER;
864 	io.ntcreatex.in.create_options = 0;
865 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
866 	io.ntcreatex.in.share_access =
867 		NTCREATEX_SHARE_ACCESS_READ |
868 		NTCREATEX_SHARE_ACCESS_WRITE;
869 	io.ntcreatex.in.alloc_size = 0;
870 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
871 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
872 	io.ntcreatex.in.security_flags = 0;
873 	io.ntcreatex.in.fname = fname;
874 	status = smb_raw_open(cli->tree, mem_ctx, &io);
875 	CHECK_STATUS(status, NT_STATUS_OK);
876 	fnum = io.ntcreatex.out.file.fnum;
877 
878 	printf("get the original sd\n");
879 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
880 	q.query_secdesc.in.file.fnum = fnum;
881 	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
882 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
883 	CHECK_STATUS(status, NT_STATUS_OK);
884 	sd_orig = q.query_secdesc.out.sd;
885 
886 	owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
887 
888 	status = smblsa_sid_check_privilege(cli,
889 					    owner_sid,
890 					    sec_privilege_name(SEC_PRIV_RESTORE));
891 	has_restore_privilege = NT_STATUS_IS_OK(status);
892 	if (!NT_STATUS_IS_OK(status)) {
893 		printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
894 	}
895 	printf("SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
896 
897 	status = smblsa_sid_check_privilege(cli,
898 					    owner_sid,
899 					    sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
900 	has_take_ownership_privilege = NT_STATUS_IS_OK(status);
901 	if (!NT_STATUS_IS_OK(status)) {
902 		printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
903 	}
904 	printf("SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
905 
906 	sd = security_descriptor_create(mem_ctx,
907 					NULL, NULL,
908 					owner_sid,
909 					SEC_ACE_TYPE_ACCESS_ALLOWED,
910 					SEC_FILE_WRITE_DATA,
911 					0,
912 					NULL);
913 
914 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
915 	set.set_secdesc.in.file.fnum = fnum;
916 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
917 	set.set_secdesc.in.sd = sd;
918 
919 	status = smb_raw_setfileinfo(cli->tree, &set);
920 	CHECK_STATUS(status, NT_STATUS_OK);
921 
922 	expected_bits = SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE;
923 
924 	for (i=0;i<16;i++) {
925 		uint32_t bit = (1<<i);
926 		io.ntcreatex.in.access_mask = bit;
927 		status = smb_raw_open(cli->tree, mem_ctx, &io);
928 		if (expected_bits & bit) {
929 			if (!NT_STATUS_IS_OK(status)) {
930 				printf("failed with access mask 0x%08x of expected 0x%08x\n",
931 				       bit, expected_bits);
932 			}
933 			CHECK_STATUS(status, NT_STATUS_OK);
934 			CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, bit | SEC_FILE_READ_ATTRIBUTE);
935 			smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
936 		} else {
937 			CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
938 		}
939 	}
940 
941 	printf("put back original sd\n");
942 	set.set_secdesc.in.sd = sd_orig;
943 	status = smb_raw_setfileinfo(cli->tree, &set);
944 	CHECK_STATUS(status, NT_STATUS_OK);
945 
946 done:
947 	smbcli_close(cli->tree, fnum);
948 	smbcli_unlink(cli->tree, fname);
949 	return ret;
950 }
951 
952 
953 
954 /*
955   test the inheritance of ACL flags onto new files and directories
956 */
test_inheritance(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)957 static BOOL test_inheritance(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
958 {
959 	NTSTATUS status;
960 	union smb_open io;
961 	const char *dname = BASEDIR "\\inheritance";
962 	const char *fname1 = BASEDIR "\\inheritance\\testfile";
963 	const char *fname2 = BASEDIR "\\inheritance\\testdir";
964 	BOOL ret = True;
965 	int fnum=0, fnum2, i;
966 	union smb_fileinfo q;
967 	union smb_setfileinfo set;
968 	struct security_descriptor *sd, *sd2, *sd_orig=NULL, *sd_def;
969 	const char *owner_sid;
970 	const struct dom_sid *creator_owner;
971 	const struct {
972 		uint32_t parent_flags;
973 		uint32_t file_flags;
974 		uint32_t dir_flags;
975 	} test_flags[] = {
976 		{
977 			0,
978 			0,
979 			0
980 		},
981 		{
982 			SEC_ACE_FLAG_OBJECT_INHERIT,
983 			0,
984 			SEC_ACE_FLAG_OBJECT_INHERIT |
985 			SEC_ACE_FLAG_INHERIT_ONLY,
986 		},
987 		{
988 			SEC_ACE_FLAG_CONTAINER_INHERIT,
989 			0,
990 			SEC_ACE_FLAG_CONTAINER_INHERIT,
991 		},
992 		{
993 			SEC_ACE_FLAG_OBJECT_INHERIT |
994 			SEC_ACE_FLAG_CONTAINER_INHERIT,
995 			0,
996 			SEC_ACE_FLAG_OBJECT_INHERIT |
997 			SEC_ACE_FLAG_CONTAINER_INHERIT,
998 		},
999 		{
1000 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1001 			0,
1002 			0,
1003 		},
1004 		{
1005 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1006 			SEC_ACE_FLAG_OBJECT_INHERIT,
1007 			0,
1008 			0,
1009 		},
1010 		{
1011 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1012 			SEC_ACE_FLAG_CONTAINER_INHERIT,
1013 			0,
1014 			0,
1015 		},
1016 		{
1017 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1018 			SEC_ACE_FLAG_CONTAINER_INHERIT |
1019 			SEC_ACE_FLAG_OBJECT_INHERIT,
1020 			0,
1021 			0,
1022 		},
1023 		{
1024 			SEC_ACE_FLAG_INHERIT_ONLY,
1025 			0,
1026 			0,
1027 		},
1028 		{
1029 			SEC_ACE_FLAG_INHERIT_ONLY |
1030 			SEC_ACE_FLAG_OBJECT_INHERIT,
1031 			0,
1032 			SEC_ACE_FLAG_OBJECT_INHERIT |
1033 			SEC_ACE_FLAG_INHERIT_ONLY,
1034 		},
1035 		{
1036 			SEC_ACE_FLAG_INHERIT_ONLY |
1037 			SEC_ACE_FLAG_CONTAINER_INHERIT,
1038 			0,
1039 			SEC_ACE_FLAG_CONTAINER_INHERIT,
1040 		},
1041 		{
1042 			SEC_ACE_FLAG_INHERIT_ONLY |
1043 			SEC_ACE_FLAG_CONTAINER_INHERIT |
1044 			SEC_ACE_FLAG_OBJECT_INHERIT,
1045 			0,
1046 			SEC_ACE_FLAG_CONTAINER_INHERIT |
1047 			SEC_ACE_FLAG_OBJECT_INHERIT,
1048 		},
1049 		{
1050 			SEC_ACE_FLAG_INHERIT_ONLY |
1051 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1052 			0,
1053 			0,
1054 		},
1055 		{
1056 			SEC_ACE_FLAG_INHERIT_ONLY |
1057 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1058 			SEC_ACE_FLAG_OBJECT_INHERIT,
1059 			0,
1060 			0,
1061 		},
1062 		{
1063 			SEC_ACE_FLAG_INHERIT_ONLY |
1064 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1065 			SEC_ACE_FLAG_CONTAINER_INHERIT,
1066 			0,
1067 			0,
1068 		},
1069 		{
1070 			SEC_ACE_FLAG_INHERIT_ONLY |
1071 			SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1072 			SEC_ACE_FLAG_CONTAINER_INHERIT |
1073 			SEC_ACE_FLAG_OBJECT_INHERIT,
1074 			0,
1075 			0,
1076 		}
1077 	};
1078 
1079 	smbcli_rmdir(cli->tree, dname);
1080 
1081 	printf("TESTING ACL INHERITANCE\n");
1082 
1083 	io.generic.level = RAW_OPEN_NTCREATEX;
1084 	io.ntcreatex.in.root_fid = 0;
1085 	io.ntcreatex.in.flags = 0;
1086 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1087 	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1088 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1089 	io.ntcreatex.in.share_access = 0;
1090 	io.ntcreatex.in.alloc_size = 0;
1091 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1092 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1093 	io.ntcreatex.in.security_flags = 0;
1094 	io.ntcreatex.in.fname = dname;
1095 
1096 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1097 	CHECK_STATUS(status, NT_STATUS_OK);
1098 	fnum = io.ntcreatex.out.file.fnum;
1099 
1100 	printf("get the original sd\n");
1101 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1102 	q.query_secdesc.in.file.fnum = fnum;
1103 	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1104 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1105 	CHECK_STATUS(status, NT_STATUS_OK);
1106 	sd_orig = q.query_secdesc.out.sd;
1107 
1108 	owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
1109 
1110 	printf("owner_sid is %s\n", owner_sid);
1111 
1112 	sd_def = security_descriptor_create(mem_ctx,
1113 					    owner_sid, NULL,
1114 					    owner_sid,
1115 					    SEC_ACE_TYPE_ACCESS_ALLOWED,
1116 					    SEC_RIGHTS_FILE_ALL,
1117 					    0,
1118 					    SID_NT_SYSTEM,
1119 					    SEC_ACE_TYPE_ACCESS_ALLOWED,
1120 					    SEC_RIGHTS_FILE_ALL,
1121 					    0,
1122 					    NULL);
1123 
1124 	creator_owner = dom_sid_parse_talloc(mem_ctx, SID_CREATOR_OWNER);
1125 
1126 	for (i=0;i<ARRAY_SIZE(test_flags);i++) {
1127 		sd = security_descriptor_create(mem_ctx,
1128 						NULL, NULL,
1129 						SID_CREATOR_OWNER,
1130 						SEC_ACE_TYPE_ACCESS_ALLOWED,
1131 						SEC_FILE_WRITE_DATA,
1132 						test_flags[i].parent_flags,
1133 						SID_WORLD,
1134 						SEC_ACE_TYPE_ACCESS_ALLOWED,
1135 						SEC_FILE_ALL | SEC_STD_ALL,
1136 						0,
1137 						NULL);
1138 		set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1139 		set.set_secdesc.in.file.fnum = fnum;
1140 		set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1141 		set.set_secdesc.in.sd = sd;
1142 		status = smb_raw_setfileinfo(cli->tree, &set);
1143 		CHECK_STATUS(status, NT_STATUS_OK);
1144 
1145 		io.ntcreatex.in.fname = fname1;
1146 		io.ntcreatex.in.create_options = 0;
1147 		status = smb_raw_open(cli->tree, mem_ctx, &io);
1148 		CHECK_STATUS(status, NT_STATUS_OK);
1149 		fnum2 = io.ntcreatex.out.file.fnum;
1150 
1151 		q.query_secdesc.in.file.fnum = fnum2;
1152 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1153 		CHECK_STATUS(status, NT_STATUS_OK);
1154 
1155 		smbcli_close(cli->tree, fnum2);
1156 		smbcli_unlink(cli->tree, fname1);
1157 
1158 		if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
1159 			if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def)) {
1160 				printf("Expected default sd at %d - got:\n", i);
1161 				NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1162 			}
1163 			goto check_dir;
1164 		}
1165 
1166 		if (q.query_secdesc.out.sd->dacl == NULL ||
1167 		    q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1168 		    q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1169 		    !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1170 				   sd_orig->owner_sid)) {
1171 			printf("Bad sd in child file at %d\n", i);
1172 			NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1173 			ret = False;
1174 			goto check_dir;
1175 		}
1176 
1177 		if (q.query_secdesc.out.sd->dacl->aces[0].flags !=
1178 		    test_flags[i].file_flags) {
1179 			printf("incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1180 			       q.query_secdesc.out.sd->dacl->aces[0].flags,
1181 			       test_flags[i].file_flags,
1182 			       test_flags[i].parent_flags,
1183 			       i);
1184 			ret = False;
1185 		}
1186 
1187 	check_dir:
1188 		io.ntcreatex.in.fname = fname2;
1189 		io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1190 		status = smb_raw_open(cli->tree, mem_ctx, &io);
1191 		CHECK_STATUS(status, NT_STATUS_OK);
1192 		fnum2 = io.ntcreatex.out.file.fnum;
1193 
1194 		q.query_secdesc.in.file.fnum = fnum2;
1195 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1196 		CHECK_STATUS(status, NT_STATUS_OK);
1197 
1198 		smbcli_close(cli->tree, fnum2);
1199 		smbcli_rmdir(cli->tree, fname2);
1200 
1201 		if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1202 		    (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT) ||
1203 		     (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT))) {
1204 			if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def)) {
1205 				printf("Expected default sd for dir at %d - got:\n", i);
1206 				NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1207 			}
1208 			continue;
1209 		}
1210 
1211 		if ((test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1212 		    (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
1213 			if (q.query_secdesc.out.sd->dacl == NULL ||
1214 			    q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1215 			    q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1216 			    !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1217 					   sd_orig->owner_sid) ||
1218 			    q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1219 				printf("Bad sd in child dir at %d (parent 0x%x)\n",
1220 				       i, test_flags[i].parent_flags);
1221 				NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1222 				ret = False;
1223 				continue;
1224 			}
1225 		} else if (test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
1226 			if (q.query_secdesc.out.sd->dacl == NULL ||
1227 			    q.query_secdesc.out.sd->dacl->num_aces != 2 ||
1228 			    q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1229 			    !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1230 					   sd_orig->owner_sid) ||
1231 			    q.query_secdesc.out.sd->dacl->aces[1].access_mask != SEC_FILE_WRITE_DATA ||
1232 			    !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[1].trustee,
1233 					   creator_owner) ||
1234 			    q.query_secdesc.out.sd->dacl->aces[0].flags != 0 ||
1235 			    q.query_secdesc.out.sd->dacl->aces[1].flags !=
1236 			    (test_flags[i].dir_flags | SEC_ACE_FLAG_INHERIT_ONLY)) {
1237 				printf("Bad sd in child dir at %d (parent 0x%x)\n",
1238 				       i, test_flags[i].parent_flags);
1239 				NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1240 				ret = False;
1241 				continue;
1242 			}
1243 		} else {
1244 			if (q.query_secdesc.out.sd->dacl == NULL ||
1245 			    q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1246 			    q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1247 			    !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1248 					   creator_owner) ||
1249 			    q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1250 				printf("Bad sd in child dir at %d (parent 0x%x)\n",
1251 				       i, test_flags[i].parent_flags);
1252 				NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1253 				ret = False;
1254 				continue;
1255 			}
1256 		}
1257 	}
1258 
1259 	printf("testing access checks on inherited create with %s\n", fname1);
1260 	sd = security_descriptor_create(mem_ctx,
1261 					NULL, NULL,
1262 					owner_sid,
1263 					SEC_ACE_TYPE_ACCESS_ALLOWED,
1264 					SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1265 					SEC_ACE_FLAG_OBJECT_INHERIT,
1266 					SID_WORLD,
1267 					SEC_ACE_TYPE_ACCESS_ALLOWED,
1268 					SEC_FILE_ALL | SEC_STD_ALL,
1269 					0,
1270 					NULL);
1271 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1272 	set.set_secdesc.in.file.fnum = fnum;
1273 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1274 	set.set_secdesc.in.sd = sd;
1275 	status = smb_raw_setfileinfo(cli->tree, &set);
1276 	CHECK_STATUS(status, NT_STATUS_OK);
1277 
1278 	io.ntcreatex.in.fname = fname1;
1279 	io.ntcreatex.in.create_options = 0;
1280 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1281 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1282 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1283 	CHECK_STATUS(status, NT_STATUS_OK);
1284 	fnum2 = io.ntcreatex.out.file.fnum;
1285 	CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1286 
1287 	q.query_secdesc.in.file.fnum = fnum2;
1288 	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1289 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1290 	CHECK_STATUS(status, NT_STATUS_OK);
1291 	smbcli_close(cli->tree, fnum2);
1292 
1293 	sd2 = security_descriptor_create(mem_ctx,
1294 					 owner_sid, NULL,
1295 					 owner_sid,
1296 					 SEC_ACE_TYPE_ACCESS_ALLOWED,
1297 					 SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1298 					 0,
1299 					 NULL);
1300 	if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
1301 		printf("%s: security descriptors don't match!\n", __location__);
1302 		printf("got:\n");
1303 		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1304 		printf("expected:\n");
1305 		NDR_PRINT_DEBUG(security_descriptor, sd2);
1306 		ret = False;
1307 	}
1308 
1309 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1310 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1311 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1312 	if (NT_STATUS_IS_OK(status)) {
1313 		printf("failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1314 		ret = False;
1315 		fnum2 = io.ntcreatex.out.file.fnum;
1316 		CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1317 		smbcli_close(cli->tree, fnum2);
1318 	} else {
1319 		CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1320 	}
1321 
1322 	printf("trying without execute\n");
1323 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1324 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL & ~SEC_FILE_EXECUTE;
1325 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1326 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1327 
1328 	printf("and with full permissions again\n");
1329 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1330 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1331 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1332 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1333 
1334 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1335 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1336 	CHECK_STATUS(status, NT_STATUS_OK);
1337 	fnum2 = io.ntcreatex.out.file.fnum;
1338 	CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1339 	smbcli_close(cli->tree, fnum2);
1340 
1341 	printf("put back original sd\n");
1342 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1343 	set.set_secdesc.in.file.fnum = fnum;
1344 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1345 	set.set_secdesc.in.sd = sd_orig;
1346 	status = smb_raw_setfileinfo(cli->tree, &set);
1347 	CHECK_STATUS(status, NT_STATUS_OK);
1348 
1349 	smbcli_close(cli->tree, fnum);
1350 
1351 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1352 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1353 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1354 
1355 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1356 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1357 	CHECK_STATUS(status, NT_STATUS_OK);
1358 	fnum2 = io.ntcreatex.out.file.fnum;
1359 	CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1360 	smbcli_close(cli->tree, fnum2);
1361 
1362 	smbcli_unlink(cli->tree, fname1);
1363 	smbcli_rmdir(cli->tree, dname);
1364 
1365 done:
1366 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1367 	set.set_secdesc.in.file.fnum = fnum;
1368 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1369 	set.set_secdesc.in.sd = sd_orig;
1370 	status = smb_raw_setfileinfo(cli->tree, &set);
1371 
1372 	smbcli_close(cli->tree, fnum);
1373 	return ret;
1374 }
1375 
1376 
1377 /*
1378   test dynamic acl inheritance
1379 */
test_inheritance_dynamic(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1380 static BOOL test_inheritance_dynamic(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1381 {
1382 	NTSTATUS status;
1383 	union smb_open io;
1384 	const char *dname = BASEDIR "\\inheritance";
1385 	const char *fname1 = BASEDIR "\\inheritance\\testfile";
1386 	BOOL ret = True;
1387 	int fnum=0, fnum2;
1388 	union smb_fileinfo q;
1389 	union smb_setfileinfo set;
1390 	struct security_descriptor *sd, *sd_orig=NULL;
1391 	const char *owner_sid;
1392 
1393 	printf("TESTING DYNAMIC ACL INHERITANCE\n");
1394 
1395 	if (!torture_setup_dir(cli, BASEDIR)) {
1396 		return False;
1397 	}
1398 
1399 	io.generic.level = RAW_OPEN_NTCREATEX;
1400 	io.ntcreatex.in.root_fid = 0;
1401 	io.ntcreatex.in.flags = 0;
1402 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1403 	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1404 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1405 	io.ntcreatex.in.share_access = 0;
1406 	io.ntcreatex.in.alloc_size = 0;
1407 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1408 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1409 	io.ntcreatex.in.security_flags = 0;
1410 	io.ntcreatex.in.fname = dname;
1411 
1412 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1413 	CHECK_STATUS(status, NT_STATUS_OK);
1414 	fnum = io.ntcreatex.out.file.fnum;
1415 
1416 	printf("get the original sd\n");
1417 	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1418 	q.query_secdesc.in.file.fnum = fnum;
1419 	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1420 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1421 	CHECK_STATUS(status, NT_STATUS_OK);
1422 	sd_orig = q.query_secdesc.out.sd;
1423 
1424 	owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
1425 
1426 	printf("owner_sid is %s\n", owner_sid);
1427 
1428 	sd = security_descriptor_create(mem_ctx,
1429 					NULL, NULL,
1430 					owner_sid,
1431 					SEC_ACE_TYPE_ACCESS_ALLOWED,
1432 					SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE,
1433 					SEC_ACE_FLAG_OBJECT_INHERIT,
1434 					NULL);
1435 	sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
1436 
1437 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1438 	set.set_secdesc.in.file.fnum = fnum;
1439 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1440 	set.set_secdesc.in.sd = sd;
1441 	status = smb_raw_setfileinfo(cli->tree, &set);
1442 	CHECK_STATUS(status, NT_STATUS_OK);
1443 
1444 	printf("create a file with an inherited acl\n");
1445 	io.ntcreatex.in.fname = fname1;
1446 	io.ntcreatex.in.create_options = 0;
1447 	io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE;
1448 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1449 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1450 	CHECK_STATUS(status, NT_STATUS_OK);
1451 	fnum2 = io.ntcreatex.out.file.fnum;
1452 	smbcli_close(cli->tree, fnum2);
1453 
1454 	printf("try and access file with base rights - should be OK\n");
1455 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1456 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1457 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1458 	CHECK_STATUS(status, NT_STATUS_OK);
1459 	fnum2 = io.ntcreatex.out.file.fnum;
1460 	smbcli_close(cli->tree, fnum2);
1461 
1462 	printf("try and access file with extra rights - should be denied\n");
1463 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
1464 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1465 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1466 
1467 	printf("update parent sd\n");
1468 	sd = security_descriptor_create(mem_ctx,
1469 					NULL, NULL,
1470 					owner_sid,
1471 					SEC_ACE_TYPE_ACCESS_ALLOWED,
1472 					SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE,
1473 					SEC_ACE_FLAG_OBJECT_INHERIT,
1474 					NULL);
1475 	sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
1476 
1477 	set.set_secdesc.in.sd = sd;
1478 	status = smb_raw_setfileinfo(cli->tree, &set);
1479 	CHECK_STATUS(status, NT_STATUS_OK);
1480 
1481 	printf("try and access file with base rights - should be OK\n");
1482 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1483 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1484 	CHECK_STATUS(status, NT_STATUS_OK);
1485 	fnum2 = io.ntcreatex.out.file.fnum;
1486 	smbcli_close(cli->tree, fnum2);
1487 
1488 
1489 	printf("try and access now - should be OK if dynamic inheritance works\n");
1490 	io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
1491 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1492 	if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1493 		printf("Server does not have dynamic inheritance\n");
1494 	}
1495 	if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1496 		printf("Server does have dynamic inheritance\n");
1497 	}
1498 	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1499 
1500 	smbcli_unlink(cli->tree, fname1);
1501 
1502 done:
1503 	printf("put back original sd\n");
1504 	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1505 	set.set_secdesc.in.file.fnum = fnum;
1506 	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1507 	set.set_secdesc.in.sd = sd_orig;
1508 	status = smb_raw_setfileinfo(cli->tree, &set);
1509 
1510 	smbcli_close(cli->tree, fnum);
1511 	smbcli_rmdir(cli->tree, dname);
1512 
1513 	return ret;
1514 }
1515 
1516 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
1517 	if (!(bits & desired_64)) {\
1518 		CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
1519 		action; \
1520 	} else { \
1521 		CHECK_STATUS(status, NT_STATUS_OK); \
1522 	} \
1523 } while (0)
1524 
1525 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
1526 	if (NT_STATUS_IS_OK(status)) { \
1527 		if (!(granted & access)) {\
1528 			printf("(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
1529 			       __location__, nt_errstr(status), access, granted, desired); \
1530 			ret = False; \
1531 			goto done; \
1532 		} \
1533 	} else { \
1534 		if (granted & access) {\
1535 			printf("(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
1536 			       __location__, nt_errstr(status), access, granted, desired); \
1537 			ret = False; \
1538 			goto done; \
1539 		} \
1540 	} \
1541 	CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
1542 } while (0)
1543 
1544 /* test what access mask is needed for getting and setting security_descriptors */
test_sd_get_set(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1545 static BOOL test_sd_get_set(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1546 {
1547 	NTSTATUS status;
1548 	BOOL ret = True;
1549 	union smb_open io;
1550 	union smb_fileinfo fi;
1551 	union smb_setfileinfo si;
1552 	struct security_descriptor *sd;
1553 	struct security_descriptor *sd_owner = NULL;
1554 	struct security_descriptor *sd_group = NULL;
1555 	struct security_descriptor *sd_dacl = NULL;
1556 	struct security_descriptor *sd_sacl = NULL;
1557 	int fnum=0;
1558 	const char *fname = BASEDIR "\\sd_get_set.txt";
1559 	uint64_t desired_64;
1560 	uint32_t desired = 0, granted;
1561 	int i = 0;
1562 #define NO_BITS_HACK (((uint64_t)1)<<32)
1563 	uint64_t open_bits =
1564 		SEC_MASK_GENERIC |
1565 		SEC_FLAG_SYSTEM_SECURITY |
1566 		SEC_FLAG_MAXIMUM_ALLOWED |
1567 		SEC_STD_ALL |
1568 		SEC_FILE_ALL |
1569 		NO_BITS_HACK;
1570 	uint64_t get_owner_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1571 	uint64_t set_owner_bits = SEC_GENERIC_ALL  | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
1572 	uint64_t get_group_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1573 	uint64_t set_group_bits = SEC_GENERIC_ALL  | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
1574 	uint64_t get_dacl_bits  = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1575 	uint64_t set_dacl_bits  = SEC_GENERIC_ALL  | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_DAC;
1576 	uint64_t get_sacl_bits  = SEC_FLAG_SYSTEM_SECURITY;
1577 	uint64_t set_sacl_bits  = SEC_FLAG_SYSTEM_SECURITY;
1578 
1579 	printf("TESTING ACCESS MASKS FOR SD GET/SET\n");
1580 
1581 	/* first create a file with full access for everyone */
1582 	sd = security_descriptor_create(mem_ctx,
1583 					SID_NT_ANONYMOUS, SID_BUILTIN_USERS,
1584 					SID_WORLD,
1585 					SEC_ACE_TYPE_ACCESS_ALLOWED,
1586 					SEC_GENERIC_ALL,
1587 					0,
1588 					NULL);
1589 	sd->type |= SEC_DESC_SACL_PRESENT;
1590 	sd->sacl = NULL;
1591 	io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
1592 	io.ntcreatex.in.root_fid = 0;
1593 	io.ntcreatex.in.flags = 0;
1594 	io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
1595 	io.ntcreatex.in.create_options = 0;
1596 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1597 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1598 	io.ntcreatex.in.alloc_size = 0;
1599 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1600 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1601 	io.ntcreatex.in.security_flags = 0;
1602 	io.ntcreatex.in.fname = fname;
1603 	io.ntcreatex.in.sec_desc = sd;
1604 	io.ntcreatex.in.ea_list = NULL;
1605 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1606 	CHECK_STATUS(status, NT_STATUS_OK);
1607 	fnum = io.ntcreatex.out.file.fnum;
1608 
1609 	status = smbcli_close(cli->tree, fnum);
1610 	CHECK_STATUS(status, NT_STATUS_OK);
1611 
1612 	/*
1613 	 * now try each access_mask bit and no bit at all in a loop
1614 	 * and see what's allowed
1615 	 * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
1616 	 */
1617 	for (i=0; i <= 32; i++) {
1618 		desired_64 = ((uint64_t)1) << i;
1619 		desired = (uint32_t)desired_64;
1620 
1621 		/* first open the file with the desired access */
1622 		io.ntcreatex.level = RAW_OPEN_NTCREATEX;
1623 		io.ntcreatex.in.access_mask = desired;
1624 		io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1625 		status = smb_raw_open(cli->tree, mem_ctx, &io);
1626 		CHECK_STATUS_FOR_BIT_ACTION(status, open_bits, goto next);
1627 		fnum = io.ntcreatex.out.file.fnum;
1628 
1629 		/* then check what access was granted */
1630 		fi.access_information.level		= RAW_FILEINFO_ACCESS_INFORMATION;
1631 		fi.access_information.in.file.fnum	= fnum;
1632 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1633 		CHECK_STATUS(status, NT_STATUS_OK);
1634 		granted = fi.access_information.out.access_flags;
1635 
1636 		/* test the owner */
1637 		ZERO_STRUCT(fi);
1638 		fi.query_secdesc.level			= RAW_FILEINFO_SEC_DESC;
1639 		fi.query_secdesc.in.file.fnum		= fnum;
1640 		fi.query_secdesc.in.secinfo_flags	= SECINFO_OWNER;
1641 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1642 		CHECK_STATUS_FOR_BIT(status, get_owner_bits, SEC_STD_READ_CONTROL);
1643 		if (fi.query_secdesc.out.sd) {
1644 			sd_owner = fi.query_secdesc.out.sd;
1645 		} else if (!sd_owner) {
1646 			sd_owner = sd;
1647 		}
1648 		si.set_secdesc.level			= RAW_SFILEINFO_SEC_DESC;
1649 		si.set_secdesc.in.file.fnum		= fnum;
1650 		si.set_secdesc.in.secinfo_flags		= SECINFO_OWNER;
1651 		si.set_secdesc.in.sd			= sd_owner;
1652 		status = smb_raw_setfileinfo(cli->tree, &si);
1653 		CHECK_STATUS_FOR_BIT(status, set_owner_bits, SEC_STD_WRITE_OWNER);
1654 
1655 		/* test the group */
1656 		ZERO_STRUCT(fi);
1657 		fi.query_secdesc.level			= RAW_FILEINFO_SEC_DESC;
1658 		fi.query_secdesc.in.file.fnum		= fnum;
1659 		fi.query_secdesc.in.secinfo_flags	= SECINFO_GROUP;
1660 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1661 		CHECK_STATUS_FOR_BIT(status, get_group_bits, SEC_STD_READ_CONTROL);
1662 		if (fi.query_secdesc.out.sd) {
1663 			sd_group = fi.query_secdesc.out.sd;
1664 		} else if (!sd_group) {
1665 			sd_group = sd;
1666 		}
1667 		si.set_secdesc.level			= RAW_SFILEINFO_SEC_DESC;
1668 		si.set_secdesc.in.file.fnum		= fnum;
1669 		si.set_secdesc.in.secinfo_flags		= SECINFO_GROUP;
1670 		si.set_secdesc.in.sd			= sd_group;
1671 		status = smb_raw_setfileinfo(cli->tree, &si);
1672 		CHECK_STATUS_FOR_BIT(status, set_group_bits, SEC_STD_WRITE_OWNER);
1673 
1674 		/* test the DACL */
1675 		ZERO_STRUCT(fi);
1676 		fi.query_secdesc.level			= RAW_FILEINFO_SEC_DESC;
1677 		fi.query_secdesc.in.file.fnum		= fnum;
1678 		fi.query_secdesc.in.secinfo_flags	= SECINFO_DACL;
1679 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1680 		CHECK_STATUS_FOR_BIT(status, get_dacl_bits, SEC_STD_READ_CONTROL);
1681 		if (fi.query_secdesc.out.sd) {
1682 			sd_dacl = fi.query_secdesc.out.sd;
1683 		} else if (!sd_dacl) {
1684 			sd_dacl = sd;
1685 		}
1686 		si.set_secdesc.level			= RAW_SFILEINFO_SEC_DESC;
1687 		si.set_secdesc.in.file.fnum		= fnum;
1688 		si.set_secdesc.in.secinfo_flags		= SECINFO_DACL;
1689 		si.set_secdesc.in.sd			= sd_dacl;
1690 		status = smb_raw_setfileinfo(cli->tree, &si);
1691 		CHECK_STATUS_FOR_BIT(status, set_dacl_bits, SEC_STD_WRITE_DAC);
1692 
1693 		/* test the SACL */
1694 		ZERO_STRUCT(fi);
1695 		fi.query_secdesc.level			= RAW_FILEINFO_SEC_DESC;
1696 		fi.query_secdesc.in.file.fnum		= fnum;
1697 		fi.query_secdesc.in.secinfo_flags	= SECINFO_SACL;
1698 		status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1699 		CHECK_STATUS_FOR_BIT(status, get_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
1700 		if (fi.query_secdesc.out.sd) {
1701 			sd_sacl = fi.query_secdesc.out.sd;
1702 		} else if (!sd_sacl) {
1703 			sd_sacl = sd;
1704 		}
1705 		si.set_secdesc.level			= RAW_SFILEINFO_SEC_DESC;
1706 		si.set_secdesc.in.file.fnum		= fnum;
1707 		si.set_secdesc.in.secinfo_flags		= SECINFO_SACL;
1708 		si.set_secdesc.in.sd			= sd_sacl;
1709 		status = smb_raw_setfileinfo(cli->tree, &si);
1710 		CHECK_STATUS_FOR_BIT(status, set_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
1711 
1712 		/* close the handle */
1713 		status = smbcli_close(cli->tree, fnum);
1714 		CHECK_STATUS(status, NT_STATUS_OK);
1715 next:
1716 		continue;
1717 	}
1718 
1719 done:
1720 	smbcli_close(cli->tree, fnum);
1721 	smbcli_unlink(cli->tree, fname);
1722 
1723 	return ret;
1724 }
1725 
1726 
1727 /*
1728    basic testing of security descriptor calls
1729 */
torture_raw_acls(struct torture_context * torture)1730 BOOL torture_raw_acls(struct torture_context *torture)
1731 {
1732 	struct smbcli_state *cli;
1733 	BOOL ret = True;
1734 	TALLOC_CTX *mem_ctx;
1735 
1736 	if (!torture_open_connection(&cli, 0)) {
1737 		return False;
1738 	}
1739 
1740 	mem_ctx = talloc_init("torture_raw_acls");
1741 
1742 	if (!torture_setup_dir(cli, BASEDIR)) {
1743 		return False;
1744 	}
1745 
1746 	ret &= test_sd(cli, mem_ctx);
1747 	ret &= test_nttrans_create(cli, mem_ctx);
1748 	ret &= test_creator_sid(cli, mem_ctx);
1749 	ret &= test_generic_bits(cli, mem_ctx);
1750 	ret &= test_owner_bits(cli, mem_ctx);
1751 	ret &= test_inheritance(cli, mem_ctx);
1752 	ret &= test_inheritance_dynamic(cli, mem_ctx);
1753 	ret &= test_sd_get_set(cli, mem_ctx);
1754 
1755 	smb_raw_exit(cli->session);
1756 	smbcli_deltree(cli->tree, BASEDIR);
1757 
1758 	torture_close_connection(cli);
1759 	talloc_free(mem_ctx);
1760 	return ret;
1761 }
1762