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