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