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