r23792: convert Samba4 to GPLv3
[kai/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 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/libcli.h"
26 #include "librpc/gen_ndr/lsa.h"
27 #include "libcli/util/clilsa.h"
28 #include "libcli/security/security.h"
29 #include "torture/util.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 = 
672                 SEC_STD_READ_CONTROL | 
673                 SEC_STD_WRITE_DAC | 
674                 SEC_STD_WRITE_OWNER;
675         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
676         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
677         io.ntcreatex.in.share_access = 
678                 NTCREATEX_SHARE_ACCESS_READ | 
679                 NTCREATEX_SHARE_ACCESS_WRITE;
680         io.ntcreatex.in.alloc_size = 0;
681         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
682         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
683         io.ntcreatex.in.security_flags = 0;
684         io.ntcreatex.in.fname = fname;
685         status = smb_raw_open(cli->tree, mem_ctx, &io);
686         CHECK_STATUS(status, NT_STATUS_OK);
687         fnum = io.ntcreatex.out.file.fnum;
688
689         printf("get the original sd\n");
690         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
691         q.query_secdesc.in.file.fnum = fnum;
692         q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
693         status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
694         CHECK_STATUS(status, NT_STATUS_OK);
695         sd_orig = q.query_secdesc.out.sd;
696
697         owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
698
699         status = smblsa_sid_check_privilege(cli, 
700                                             owner_sid, 
701                                             sec_privilege_name(SEC_PRIV_RESTORE));
702         has_restore_privilege = NT_STATUS_IS_OK(status);
703         if (!NT_STATUS_IS_OK(status)) {
704                 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
705         }
706         printf("SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
707
708         status = smblsa_sid_check_privilege(cli, 
709                                             owner_sid, 
710                                             sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
711         has_take_ownership_privilege = NT_STATUS_IS_OK(status);
712         if (!NT_STATUS_IS_OK(status)) {
713                 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
714         }
715         printf("SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
716
717         for (i=0;i<ARRAY_SIZE(dir_mappings);i++) {
718                 uint32_t expected_mask = 
719                         SEC_STD_WRITE_DAC | 
720                         SEC_STD_READ_CONTROL | 
721                         SEC_FILE_READ_ATTRIBUTE |
722                         SEC_STD_DELETE;
723                 uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
724
725                 if (has_restore_privilege) {
726                         expected_mask_anon |= SEC_STD_DELETE;
727                 }
728
729                 printf("testing generic bits 0x%08x\n", 
730                        file_mappings[i].gen_bits);
731                 sd = security_descriptor_create(mem_ctx,
732                                                 owner_sid, NULL,
733                                                 owner_sid,
734                                                 SEC_ACE_TYPE_ACCESS_ALLOWED,
735                                                 dir_mappings[i].gen_bits,
736                                                 0,
737                                                 NULL);
738
739                 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
740                 set.set_secdesc.in.file.fnum = fnum;
741                 set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
742                 set.set_secdesc.in.sd = sd;
743
744                 status = smb_raw_setfileinfo(cli->tree, &set);
745                 CHECK_STATUS(status, NT_STATUS_OK);
746
747                 sd2 = security_descriptor_create(mem_ctx,
748                                                  owner_sid, NULL,
749                                                  owner_sid,
750                                                  SEC_ACE_TYPE_ACCESS_ALLOWED,
751                                                  dir_mappings[i].specific_bits,
752                                                  0,
753                                                  NULL);
754
755                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
756                 CHECK_STATUS(status, NT_STATUS_OK);
757                 if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
758                         printf("%s: security descriptors don't match!\n", __location__);
759                         printf("got:\n");
760                         NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
761                         printf("expected:\n");
762                         NDR_PRINT_DEBUG(security_descriptor, sd2);
763                         ret = False;
764                 }
765
766                 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
767                 status = smb_raw_open(cli->tree, mem_ctx, &io);
768                 CHECK_STATUS(status, NT_STATUS_OK);
769                 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, 
770                                    expected_mask | dir_mappings[i].specific_bits);
771                 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
772
773                 if (!has_take_ownership_privilege) {
774                         continue;
775                 }
776
777                 printf("testing generic bits 0x%08x (anonymous)\n", 
778                        file_mappings[i].gen_bits);
779                 sd = security_descriptor_create(mem_ctx,
780                                                 SID_NT_ANONYMOUS, NULL,
781                                                 owner_sid,
782                                                 SEC_ACE_TYPE_ACCESS_ALLOWED,
783                                                 file_mappings[i].gen_bits,
784                                                 0,
785                                                 NULL);
786
787                 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
788                 set.set_secdesc.in.file.fnum = fnum;
789                 set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
790                 set.set_secdesc.in.sd = sd;
791
792                 status = smb_raw_setfileinfo(cli->tree, &set);
793                 CHECK_STATUS(status, NT_STATUS_OK);
794
795                 sd2 = security_descriptor_create(mem_ctx,
796                                                  SID_NT_ANONYMOUS, NULL,
797                                                  owner_sid,
798                                                  SEC_ACE_TYPE_ACCESS_ALLOWED,
799                                                  file_mappings[i].specific_bits,
800                                                  0,
801                                                  NULL);
802
803                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
804                 CHECK_STATUS(status, NT_STATUS_OK);
805                 if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
806                         printf("%s: security descriptors don't match!\n", __location__);
807                         printf("got:\n");
808                         NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
809                         printf("expected:\n");
810                         NDR_PRINT_DEBUG(security_descriptor, sd2);
811                         ret = False;
812                 }
813
814                 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
815                 status = smb_raw_open(cli->tree, mem_ctx, &io);
816                 CHECK_STATUS(status, NT_STATUS_OK);
817                 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, 
818                                    expected_mask_anon | dir_mappings[i].specific_bits);
819                 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
820         }
821
822         printf("put back original sd\n");
823         set.set_secdesc.in.sd = sd_orig;
824         status = smb_raw_setfileinfo(cli->tree, &set);
825         CHECK_STATUS(status, NT_STATUS_OK);
826
827         smbcli_close(cli->tree, fnum);
828         smbcli_unlink(cli->tree, fname);
829
830 done:
831         smbcli_close(cli->tree, fnum);
832         return ret;
833 }
834
835
836 /*
837   see what access bits the owner of a file always gets
838 */
839 static BOOL test_owner_bits(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
840 {
841         NTSTATUS status;
842         union smb_open io;
843         const char *fname = BASEDIR "\\generic.txt";
844         BOOL ret = True;
845         int fnum = -1, i;
846         union smb_fileinfo q;
847         union smb_setfileinfo set;
848         struct security_descriptor *sd, *sd_orig;
849         const char *owner_sid;
850         BOOL has_restore_privilege;
851         BOOL has_take_ownership_privilege;
852         uint32_t expected_bits;
853
854         printf("TESTING FILE OWNER BITS\n");
855
856         io.generic.level = RAW_OPEN_NTCREATEX;
857         io.ntcreatex.in.root_fid = 0;
858         io.ntcreatex.in.flags = 0;
859         io.ntcreatex.in.access_mask = 
860                 SEC_STD_READ_CONTROL | 
861                 SEC_STD_WRITE_DAC | 
862                 SEC_STD_WRITE_OWNER;
863         io.ntcreatex.in.create_options = 0;
864         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
865         io.ntcreatex.in.share_access = 
866                 NTCREATEX_SHARE_ACCESS_READ | 
867                 NTCREATEX_SHARE_ACCESS_WRITE;
868         io.ntcreatex.in.alloc_size = 0;
869         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
870         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
871         io.ntcreatex.in.security_flags = 0;
872         io.ntcreatex.in.fname = fname;
873         status = smb_raw_open(cli->tree, mem_ctx, &io);
874         CHECK_STATUS(status, NT_STATUS_OK);
875         fnum = io.ntcreatex.out.file.fnum;
876
877         printf("get the original sd\n");
878         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
879         q.query_secdesc.in.file.fnum = fnum;
880         q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
881         status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
882         CHECK_STATUS(status, NT_STATUS_OK);
883         sd_orig = q.query_secdesc.out.sd;
884
885         owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
886
887         status = smblsa_sid_check_privilege(cli, 
888                                             owner_sid, 
889                                             sec_privilege_name(SEC_PRIV_RESTORE));
890         has_restore_privilege = NT_STATUS_IS_OK(status);
891         if (!NT_STATUS_IS_OK(status)) {
892                 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
893         }
894         printf("SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
895
896         status = smblsa_sid_check_privilege(cli, 
897                                             owner_sid, 
898                                             sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
899         has_take_ownership_privilege = NT_STATUS_IS_OK(status);
900         if (!NT_STATUS_IS_OK(status)) {
901                 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status));
902         }
903         printf("SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
904
905         sd = security_descriptor_create(mem_ctx,
906                                         NULL, NULL,
907                                         owner_sid,
908                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
909                                         SEC_FILE_WRITE_DATA,
910                                         0,
911                                         NULL);
912
913         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
914         set.set_secdesc.in.file.fnum = fnum;
915         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
916         set.set_secdesc.in.sd = sd;
917
918         status = smb_raw_setfileinfo(cli->tree, &set);
919         CHECK_STATUS(status, NT_STATUS_OK);
920
921         expected_bits = SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE;
922
923         for (i=0;i<16;i++) {
924                 uint32_t bit = (1<<i);
925                 io.ntcreatex.in.access_mask = bit;
926                 status = smb_raw_open(cli->tree, mem_ctx, &io);
927                 if (expected_bits & bit) {
928                         if (!NT_STATUS_IS_OK(status)) {
929                                 printf("failed with access mask 0x%08x of expected 0x%08x\n",
930                                        bit, expected_bits);
931                         }
932                         CHECK_STATUS(status, NT_STATUS_OK);
933                         CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, bit | SEC_FILE_READ_ATTRIBUTE);
934                         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
935                 } else {
936                         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
937                 }
938         }
939
940         printf("put back original sd\n");
941         set.set_secdesc.in.sd = sd_orig;
942         status = smb_raw_setfileinfo(cli->tree, &set);
943         CHECK_STATUS(status, NT_STATUS_OK);
944
945 done:
946         smbcli_close(cli->tree, fnum);
947         smbcli_unlink(cli->tree, fname);
948         return ret;
949 }
950
951
952
953 /*
954   test the inheritance of ACL flags onto new files and directories
955 */
956 static BOOL test_inheritance(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
957 {
958         NTSTATUS status;
959         union smb_open io;
960         const char *dname = BASEDIR "\\inheritance";
961         const char *fname1 = BASEDIR "\\inheritance\\testfile";
962         const char *fname2 = BASEDIR "\\inheritance\\testdir";
963         BOOL ret = True;
964         int fnum=0, fnum2, i;
965         union smb_fileinfo q;
966         union smb_setfileinfo set;
967         struct security_descriptor *sd, *sd2, *sd_orig=NULL, *sd_def;
968         const char *owner_sid;
969         const struct dom_sid *creator_owner;
970         const struct {
971                 uint32_t parent_flags;
972                 uint32_t file_flags;
973                 uint32_t dir_flags;
974         } test_flags[] = {
975                 {
976                         0, 
977                         0,
978                         0
979                 },
980                 {
981                         SEC_ACE_FLAG_OBJECT_INHERIT,
982                         0,
983                         SEC_ACE_FLAG_OBJECT_INHERIT | 
984                         SEC_ACE_FLAG_INHERIT_ONLY,
985                 },
986                 {
987                         SEC_ACE_FLAG_CONTAINER_INHERIT,
988                         0,
989                         SEC_ACE_FLAG_CONTAINER_INHERIT,
990                 },
991                 {
992                         SEC_ACE_FLAG_OBJECT_INHERIT | 
993                         SEC_ACE_FLAG_CONTAINER_INHERIT,
994                         0,
995                         SEC_ACE_FLAG_OBJECT_INHERIT | 
996                         SEC_ACE_FLAG_CONTAINER_INHERIT,
997                 },
998                 {
999                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1000                         0,
1001                         0,
1002                 },
1003                 {
1004                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT | 
1005                         SEC_ACE_FLAG_OBJECT_INHERIT,
1006                         0,
1007                         0,
1008                 },
1009                 {
1010                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT | 
1011                         SEC_ACE_FLAG_CONTAINER_INHERIT,
1012                         0,
1013                         0,
1014                 },
1015                 {
1016                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT | 
1017                         SEC_ACE_FLAG_CONTAINER_INHERIT | 
1018                         SEC_ACE_FLAG_OBJECT_INHERIT,
1019                         0,
1020                         0,
1021                 },
1022                 {
1023                         SEC_ACE_FLAG_INHERIT_ONLY,
1024                         0,
1025                         0,
1026                 },
1027                 {
1028                         SEC_ACE_FLAG_INHERIT_ONLY | 
1029                         SEC_ACE_FLAG_OBJECT_INHERIT,
1030                         0,
1031                         SEC_ACE_FLAG_OBJECT_INHERIT | 
1032                         SEC_ACE_FLAG_INHERIT_ONLY,
1033                 },
1034                 {
1035                         SEC_ACE_FLAG_INHERIT_ONLY | 
1036                         SEC_ACE_FLAG_CONTAINER_INHERIT,
1037                         0,
1038                         SEC_ACE_FLAG_CONTAINER_INHERIT,
1039                 },
1040                 {
1041                         SEC_ACE_FLAG_INHERIT_ONLY | 
1042                         SEC_ACE_FLAG_CONTAINER_INHERIT | 
1043                         SEC_ACE_FLAG_OBJECT_INHERIT,
1044                         0,
1045                         SEC_ACE_FLAG_CONTAINER_INHERIT | 
1046                         SEC_ACE_FLAG_OBJECT_INHERIT,
1047                 },
1048                 {
1049                         SEC_ACE_FLAG_INHERIT_ONLY | 
1050                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1051                         0,
1052                         0,
1053                 },
1054                 {
1055                         SEC_ACE_FLAG_INHERIT_ONLY | 
1056                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT | 
1057                         SEC_ACE_FLAG_OBJECT_INHERIT,
1058                         0,
1059                         0,
1060                 },
1061                 {
1062                         SEC_ACE_FLAG_INHERIT_ONLY | 
1063                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT | 
1064                         SEC_ACE_FLAG_CONTAINER_INHERIT,
1065                         0,
1066                         0,
1067                 },
1068                 {
1069                         SEC_ACE_FLAG_INHERIT_ONLY | 
1070                         SEC_ACE_FLAG_NO_PROPAGATE_INHERIT | 
1071                         SEC_ACE_FLAG_CONTAINER_INHERIT | 
1072                         SEC_ACE_FLAG_OBJECT_INHERIT,
1073                         0,
1074                         0,
1075                 }
1076         };
1077
1078         smbcli_rmdir(cli->tree, dname);
1079
1080         printf("TESTING ACL INHERITANCE\n");
1081
1082         io.generic.level = RAW_OPEN_NTCREATEX;
1083         io.ntcreatex.in.root_fid = 0;
1084         io.ntcreatex.in.flags = 0;
1085         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1086         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1087         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1088         io.ntcreatex.in.share_access = 0;
1089         io.ntcreatex.in.alloc_size = 0;
1090         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1091         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1092         io.ntcreatex.in.security_flags = 0;
1093         io.ntcreatex.in.fname = dname;
1094
1095         status = smb_raw_open(cli->tree, mem_ctx, &io);
1096         CHECK_STATUS(status, NT_STATUS_OK);
1097         fnum = io.ntcreatex.out.file.fnum;
1098
1099         printf("get the original sd\n");
1100         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1101         q.query_secdesc.in.file.fnum = fnum;
1102         q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1103         status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1104         CHECK_STATUS(status, NT_STATUS_OK);
1105         sd_orig = q.query_secdesc.out.sd;
1106
1107         owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
1108
1109         printf("owner_sid is %s\n", owner_sid);
1110
1111         sd_def = security_descriptor_create(mem_ctx,
1112                                             owner_sid, NULL,
1113                                             owner_sid,
1114                                             SEC_ACE_TYPE_ACCESS_ALLOWED,
1115                                             SEC_RIGHTS_FILE_ALL,
1116                                             0,
1117                                             SID_NT_SYSTEM,
1118                                             SEC_ACE_TYPE_ACCESS_ALLOWED,
1119                                             SEC_RIGHTS_FILE_ALL,
1120                                             0,
1121                                             NULL);
1122
1123         creator_owner = dom_sid_parse_talloc(mem_ctx, SID_CREATOR_OWNER);
1124
1125         for (i=0;i<ARRAY_SIZE(test_flags);i++) {
1126                 sd = security_descriptor_create(mem_ctx,
1127                                                 NULL, NULL,
1128                                                 SID_CREATOR_OWNER,
1129                                                 SEC_ACE_TYPE_ACCESS_ALLOWED,
1130                                                 SEC_FILE_WRITE_DATA,
1131                                                 test_flags[i].parent_flags,
1132                                                 SID_WORLD,
1133                                                 SEC_ACE_TYPE_ACCESS_ALLOWED,
1134                                                 SEC_FILE_ALL | SEC_STD_ALL,
1135                                                 0,
1136                                                 NULL);
1137                 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1138                 set.set_secdesc.in.file.fnum = fnum;
1139                 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1140                 set.set_secdesc.in.sd = sd;
1141                 status = smb_raw_setfileinfo(cli->tree, &set);
1142                 CHECK_STATUS(status, NT_STATUS_OK);
1143
1144                 io.ntcreatex.in.fname = fname1;
1145                 io.ntcreatex.in.create_options = 0;
1146                 status = smb_raw_open(cli->tree, mem_ctx, &io);
1147                 CHECK_STATUS(status, NT_STATUS_OK);
1148                 fnum2 = io.ntcreatex.out.file.fnum;
1149
1150                 q.query_secdesc.in.file.fnum = fnum2;
1151                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1152                 CHECK_STATUS(status, NT_STATUS_OK);
1153
1154                 smbcli_close(cli->tree, fnum2);
1155                 smbcli_unlink(cli->tree, fname1);
1156
1157                 if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
1158                         if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def)) {
1159                                 printf("Expected default sd at %d - got:\n", i);
1160                                 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1161                         }
1162                         goto check_dir;
1163                 }
1164
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                                    sd_orig->owner_sid)) {
1170                         printf("Bad sd in child file at %d\n", i);
1171                         NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1172                         ret = False;
1173                         goto check_dir;
1174                 }
1175
1176                 if (q.query_secdesc.out.sd->dacl->aces[0].flags != 
1177                     test_flags[i].file_flags) {
1178                         printf("incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1179                                q.query_secdesc.out.sd->dacl->aces[0].flags,
1180                                test_flags[i].file_flags,
1181                                test_flags[i].parent_flags,
1182                                i);
1183                         ret = False;
1184                 }
1185
1186         check_dir:
1187                 io.ntcreatex.in.fname = fname2;
1188                 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1189                 status = smb_raw_open(cli->tree, mem_ctx, &io);
1190                 CHECK_STATUS(status, NT_STATUS_OK);
1191                 fnum2 = io.ntcreatex.out.file.fnum;
1192
1193                 q.query_secdesc.in.file.fnum = fnum2;
1194                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1195                 CHECK_STATUS(status, NT_STATUS_OK);
1196
1197                 smbcli_close(cli->tree, fnum2);
1198                 smbcli_rmdir(cli->tree, fname2);
1199
1200                 if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1201                     (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT) ||
1202                      (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT))) {
1203                         if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def)) {
1204                                 printf("Expected default sd for dir at %d - got:\n", i);
1205                                 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1206                         }
1207                         continue;
1208                 }
1209
1210                 if ((test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) && 
1211                     (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
1212                         if (q.query_secdesc.out.sd->dacl == NULL ||
1213                             q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1214                             q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1215                             !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1216                                            sd_orig->owner_sid) ||
1217                             q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1218                                 printf("Bad sd in child dir at %d (parent 0x%x)\n", 
1219                                        i, test_flags[i].parent_flags);
1220                                 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1221                                 ret = False;
1222                                 continue;
1223                         }
1224                 } else if (test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
1225                         if (q.query_secdesc.out.sd->dacl == NULL ||
1226                             q.query_secdesc.out.sd->dacl->num_aces != 2 ||
1227                             q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1228                             !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1229                                            sd_orig->owner_sid) ||
1230                             q.query_secdesc.out.sd->dacl->aces[1].access_mask != SEC_FILE_WRITE_DATA ||
1231                             !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[1].trustee,
1232                                            creator_owner) ||
1233                             q.query_secdesc.out.sd->dacl->aces[0].flags != 0 ||
1234                             q.query_secdesc.out.sd->dacl->aces[1].flags != 
1235                             (test_flags[i].dir_flags | SEC_ACE_FLAG_INHERIT_ONLY)) {
1236                                 printf("Bad sd in child dir at %d (parent 0x%x)\n", 
1237                                        i, test_flags[i].parent_flags);
1238                                 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1239                                 ret = False;
1240                                 continue;
1241                         }
1242                 } else {
1243                         if (q.query_secdesc.out.sd->dacl == NULL ||
1244                             q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1245                             q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1246                             !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1247                                            creator_owner) ||
1248                             q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1249                                 printf("Bad sd in child dir at %d (parent 0x%x)\n", 
1250                                        i, test_flags[i].parent_flags);
1251                                 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1252                                 ret = False;
1253                                 continue;
1254                         }
1255                 }
1256         }
1257
1258         printf("testing access checks on inherited create with %s\n", fname1);
1259         sd = security_descriptor_create(mem_ctx,
1260                                         NULL, NULL,
1261                                         owner_sid,
1262                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
1263                                         SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1264                                         SEC_ACE_FLAG_OBJECT_INHERIT,
1265                                         SID_WORLD,
1266                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
1267                                         SEC_FILE_ALL | SEC_STD_ALL,
1268                                         0,
1269                                         NULL);
1270         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1271         set.set_secdesc.in.file.fnum = fnum;
1272         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1273         set.set_secdesc.in.sd = sd;
1274         status = smb_raw_setfileinfo(cli->tree, &set);
1275         CHECK_STATUS(status, NT_STATUS_OK);
1276
1277         io.ntcreatex.in.fname = fname1;
1278         io.ntcreatex.in.create_options = 0;
1279         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1280         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1281         status = smb_raw_open(cli->tree, mem_ctx, &io);
1282         CHECK_STATUS(status, NT_STATUS_OK);
1283         fnum2 = io.ntcreatex.out.file.fnum;
1284         CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1285
1286         q.query_secdesc.in.file.fnum = fnum2;
1287         q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1288         status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1289         CHECK_STATUS(status, NT_STATUS_OK);
1290         smbcli_close(cli->tree, fnum2);
1291
1292         sd2 = security_descriptor_create(mem_ctx,
1293                                          owner_sid, NULL,
1294                                          owner_sid,
1295                                          SEC_ACE_TYPE_ACCESS_ALLOWED,
1296                                          SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1297                                          0,
1298                                          NULL);
1299         if (!security_descriptor_equal(q.query_secdesc.out.sd, sd2)) {
1300                 printf("%s: security descriptors don't match!\n", __location__);
1301                 printf("got:\n");
1302                 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1303                 printf("expected:\n");
1304                 NDR_PRINT_DEBUG(security_descriptor, sd2);
1305                 ret = False;
1306         }
1307
1308         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1309         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1310         status = smb_raw_open(cli->tree, mem_ctx, &io);
1311         if (NT_STATUS_IS_OK(status)) {
1312                 printf("failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1313                 ret = False;
1314                 fnum2 = io.ntcreatex.out.file.fnum;
1315                 CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1316                 smbcli_close(cli->tree, fnum2);
1317         } else {
1318                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1319         }
1320
1321         printf("trying without execute\n");
1322         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1323         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL & ~SEC_FILE_EXECUTE;
1324         status = smb_raw_open(cli->tree, mem_ctx, &io);
1325         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1326
1327         printf("and with full permissions again\n");
1328         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1329         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1330         status = smb_raw_open(cli->tree, mem_ctx, &io);
1331         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1332
1333         io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1334         status = smb_raw_open(cli->tree, mem_ctx, &io);
1335         CHECK_STATUS(status, NT_STATUS_OK);
1336         fnum2 = io.ntcreatex.out.file.fnum;
1337         CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1338         smbcli_close(cli->tree, fnum2);
1339
1340         printf("put back original sd\n");
1341         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1342         set.set_secdesc.in.file.fnum = fnum;
1343         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1344         set.set_secdesc.in.sd = sd_orig;
1345         status = smb_raw_setfileinfo(cli->tree, &set);
1346         CHECK_STATUS(status, NT_STATUS_OK);
1347
1348         smbcli_close(cli->tree, fnum);
1349
1350         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1351         status = smb_raw_open(cli->tree, mem_ctx, &io);
1352         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1353
1354         io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1355         status = smb_raw_open(cli->tree, mem_ctx, &io);
1356         CHECK_STATUS(status, NT_STATUS_OK);
1357         fnum2 = io.ntcreatex.out.file.fnum;
1358         CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1359         smbcli_close(cli->tree, fnum2);
1360
1361         smbcli_unlink(cli->tree, fname1);
1362         smbcli_rmdir(cli->tree, dname);
1363
1364 done:
1365         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1366         set.set_secdesc.in.file.fnum = fnum;
1367         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1368         set.set_secdesc.in.sd = sd_orig;
1369         status = smb_raw_setfileinfo(cli->tree, &set);
1370
1371         smbcli_close(cli->tree, fnum);
1372         return ret;
1373 }
1374
1375
1376 /*
1377   test dynamic acl inheritance
1378 */
1379 static BOOL test_inheritance_dynamic(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1380 {
1381         NTSTATUS status;
1382         union smb_open io;
1383         const char *dname = BASEDIR "\\inheritance";
1384         const char *fname1 = BASEDIR "\\inheritance\\testfile";
1385         BOOL ret = True;
1386         int fnum=0, fnum2;
1387         union smb_fileinfo q;
1388         union smb_setfileinfo set;
1389         struct security_descriptor *sd, *sd_orig=NULL;
1390         const char *owner_sid;
1391         
1392         printf("TESTING DYNAMIC ACL INHERITANCE\n");
1393
1394         if (!torture_setup_dir(cli, BASEDIR)) {
1395                 return False;
1396         }
1397
1398         io.generic.level = RAW_OPEN_NTCREATEX;
1399         io.ntcreatex.in.root_fid = 0;
1400         io.ntcreatex.in.flags = 0;
1401         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1402         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1403         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1404         io.ntcreatex.in.share_access = 0;
1405         io.ntcreatex.in.alloc_size = 0;
1406         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1407         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1408         io.ntcreatex.in.security_flags = 0;
1409         io.ntcreatex.in.fname = dname;
1410
1411         status = smb_raw_open(cli->tree, mem_ctx, &io);
1412         CHECK_STATUS(status, NT_STATUS_OK);
1413         fnum = io.ntcreatex.out.file.fnum;
1414
1415         printf("get the original sd\n");
1416         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1417         q.query_secdesc.in.file.fnum = fnum;
1418         q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1419         status = smb_raw_fileinfo(cli->tree, mem_ctx, &q);
1420         CHECK_STATUS(status, NT_STATUS_OK);
1421         sd_orig = q.query_secdesc.out.sd;
1422
1423         owner_sid = dom_sid_string(mem_ctx, sd_orig->owner_sid);
1424
1425         printf("owner_sid is %s\n", owner_sid);
1426
1427         sd = security_descriptor_create(mem_ctx,
1428                                         NULL, NULL,
1429                                         owner_sid,
1430                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
1431                                         SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE,
1432                                         SEC_ACE_FLAG_OBJECT_INHERIT,
1433                                         NULL);
1434         sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
1435
1436         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1437         set.set_secdesc.in.file.fnum = fnum;
1438         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1439         set.set_secdesc.in.sd = sd;
1440         status = smb_raw_setfileinfo(cli->tree, &set);
1441         CHECK_STATUS(status, NT_STATUS_OK);
1442
1443         printf("create a file with an inherited acl\n");
1444         io.ntcreatex.in.fname = fname1;
1445         io.ntcreatex.in.create_options = 0;
1446         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE;
1447         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1448         status = smb_raw_open(cli->tree, mem_ctx, &io);
1449         CHECK_STATUS(status, NT_STATUS_OK);
1450         fnum2 = io.ntcreatex.out.file.fnum;
1451         smbcli_close(cli->tree, fnum2);
1452
1453         printf("try and access file with base rights - should be OK\n");
1454         io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1455         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1456         status = smb_raw_open(cli->tree, mem_ctx, &io);
1457         CHECK_STATUS(status, NT_STATUS_OK);
1458         fnum2 = io.ntcreatex.out.file.fnum;
1459         smbcli_close(cli->tree, fnum2);
1460
1461         printf("try and access file with extra rights - should be denied\n");
1462         io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
1463         status = smb_raw_open(cli->tree, mem_ctx, &io);
1464         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1465
1466         printf("update parent sd\n");
1467         sd = security_descriptor_create(mem_ctx,
1468                                         NULL, NULL,
1469                                         owner_sid,
1470                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
1471                                         SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE,
1472                                         SEC_ACE_FLAG_OBJECT_INHERIT,
1473                                         NULL);
1474         sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
1475
1476         set.set_secdesc.in.sd = sd;
1477         status = smb_raw_setfileinfo(cli->tree, &set);
1478         CHECK_STATUS(status, NT_STATUS_OK);
1479
1480         printf("try and access file with base rights - should be OK\n");
1481         io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1482         status = smb_raw_open(cli->tree, mem_ctx, &io);
1483         CHECK_STATUS(status, NT_STATUS_OK);
1484         fnum2 = io.ntcreatex.out.file.fnum;
1485         smbcli_close(cli->tree, fnum2);
1486
1487
1488         printf("try and access now - should be OK if dynamic inheritance works\n");
1489         io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
1490         status = smb_raw_open(cli->tree, mem_ctx, &io);
1491         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1492                 printf("Server does not have dynamic inheritance\n");
1493         }
1494         if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1495                 printf("Server does have dynamic inheritance\n");
1496         }
1497         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1498
1499         smbcli_unlink(cli->tree, fname1);
1500
1501 done:
1502         printf("put back original sd\n");
1503         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1504         set.set_secdesc.in.file.fnum = fnum;
1505         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1506         set.set_secdesc.in.sd = sd_orig;
1507         status = smb_raw_setfileinfo(cli->tree, &set);
1508
1509         smbcli_close(cli->tree, fnum);
1510         smbcli_rmdir(cli->tree, dname);
1511
1512         return ret;
1513 }
1514
1515 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
1516         if (!(bits & desired_64)) {\
1517                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
1518                 action; \
1519         } else { \
1520                 CHECK_STATUS(status, NT_STATUS_OK); \
1521         } \
1522 } while (0)
1523
1524 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
1525         if (NT_STATUS_IS_OK(status)) { \
1526                 if (!(granted & access)) {\
1527                         printf("(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
1528                                __location__, nt_errstr(status), access, granted, desired); \
1529                         ret = False; \
1530                         goto done; \
1531                 } \
1532         } else { \
1533                 if (granted & access) {\
1534                         printf("(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
1535                                __location__, nt_errstr(status), access, granted, desired); \
1536                         ret = False; \
1537                         goto done; \
1538                 } \
1539         } \
1540         CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
1541 } while (0)
1542
1543 /* test what access mask is needed for getting and setting security_descriptors */
1544 static BOOL test_sd_get_set(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1545 {
1546         NTSTATUS status;
1547         BOOL ret = True;
1548         union smb_open io;
1549         union smb_fileinfo fi;
1550         union smb_setfileinfo si;
1551         struct security_descriptor *sd;
1552         struct security_descriptor *sd_owner = NULL;
1553         struct security_descriptor *sd_group = NULL;
1554         struct security_descriptor *sd_dacl = NULL;
1555         struct security_descriptor *sd_sacl = NULL;
1556         int fnum=0;
1557         const char *fname = BASEDIR "\\sd_get_set.txt";
1558         uint64_t desired_64;
1559         uint32_t desired = 0, granted;
1560         int i = 0;
1561 #define NO_BITS_HACK (((uint64_t)1)<<32)
1562         uint64_t open_bits =
1563                 SEC_MASK_GENERIC |
1564                 SEC_FLAG_SYSTEM_SECURITY |
1565                 SEC_FLAG_MAXIMUM_ALLOWED |
1566                 SEC_STD_ALL |
1567                 SEC_FILE_ALL | 
1568                 NO_BITS_HACK;
1569         uint64_t get_owner_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1570         uint64_t set_owner_bits = SEC_GENERIC_ALL  | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
1571         uint64_t get_group_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1572         uint64_t set_group_bits = SEC_GENERIC_ALL  | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
1573         uint64_t get_dacl_bits  = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
1574         uint64_t set_dacl_bits  = SEC_GENERIC_ALL  | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_DAC;
1575         uint64_t get_sacl_bits  = SEC_FLAG_SYSTEM_SECURITY;
1576         uint64_t set_sacl_bits  = SEC_FLAG_SYSTEM_SECURITY;
1577
1578         printf("TESTING ACCESS MASKS FOR SD GET/SET\n");
1579
1580         /* first create a file with full access for everyone */
1581         sd = security_descriptor_create(mem_ctx,
1582                                         SID_NT_ANONYMOUS, SID_BUILTIN_USERS,
1583                                         SID_WORLD,
1584                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
1585                                         SEC_GENERIC_ALL,
1586                                         0,
1587                                         NULL);
1588         sd->type |= SEC_DESC_SACL_PRESENT;
1589         sd->sacl = NULL;
1590         io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
1591         io.ntcreatex.in.root_fid = 0;
1592         io.ntcreatex.in.flags = 0;
1593         io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
1594         io.ntcreatex.in.create_options = 0;
1595         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1596         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1597         io.ntcreatex.in.alloc_size = 0;
1598         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1599         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1600         io.ntcreatex.in.security_flags = 0;
1601         io.ntcreatex.in.fname = fname;
1602         io.ntcreatex.in.sec_desc = sd;
1603         io.ntcreatex.in.ea_list = NULL;
1604         status = smb_raw_open(cli->tree, mem_ctx, &io);
1605         CHECK_STATUS(status, NT_STATUS_OK);
1606         fnum = io.ntcreatex.out.file.fnum;
1607
1608         status = smbcli_close(cli->tree, fnum);
1609         CHECK_STATUS(status, NT_STATUS_OK);
1610
1611         /* 
1612          * now try each access_mask bit and no bit at all in a loop
1613          * and see what's allowed
1614          * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
1615          */
1616         for (i=0; i <= 32; i++) {
1617                 desired_64 = ((uint64_t)1) << i;
1618                 desired = (uint32_t)desired_64;
1619
1620                 /* first open the file with the desired access */
1621                 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
1622                 io.ntcreatex.in.access_mask = desired;
1623                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1624                 status = smb_raw_open(cli->tree, mem_ctx, &io);
1625                 CHECK_STATUS_FOR_BIT_ACTION(status, open_bits, goto next);
1626                 fnum = io.ntcreatex.out.file.fnum;
1627
1628                 /* then check what access was granted */
1629                 fi.access_information.level             = RAW_FILEINFO_ACCESS_INFORMATION;
1630                 fi.access_information.in.file.fnum      = fnum;
1631                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1632                 CHECK_STATUS(status, NT_STATUS_OK);
1633                 granted = fi.access_information.out.access_flags;
1634
1635                 /* test the owner */
1636                 ZERO_STRUCT(fi);
1637                 fi.query_secdesc.level                  = RAW_FILEINFO_SEC_DESC;
1638                 fi.query_secdesc.in.file.fnum           = fnum;
1639                 fi.query_secdesc.in.secinfo_flags       = SECINFO_OWNER;
1640                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1641                 CHECK_STATUS_FOR_BIT(status, get_owner_bits, SEC_STD_READ_CONTROL);
1642                 if (fi.query_secdesc.out.sd) {
1643                         sd_owner = fi.query_secdesc.out.sd;
1644                 } else if (!sd_owner) {
1645                         sd_owner = sd;
1646                 }
1647                 si.set_secdesc.level                    = RAW_SFILEINFO_SEC_DESC;
1648                 si.set_secdesc.in.file.fnum             = fnum;
1649                 si.set_secdesc.in.secinfo_flags         = SECINFO_OWNER;
1650                 si.set_secdesc.in.sd                    = sd_owner;
1651                 status = smb_raw_setfileinfo(cli->tree, &si);
1652                 CHECK_STATUS_FOR_BIT(status, set_owner_bits, SEC_STD_WRITE_OWNER);
1653
1654                 /* test the group */
1655                 ZERO_STRUCT(fi);
1656                 fi.query_secdesc.level                  = RAW_FILEINFO_SEC_DESC;
1657                 fi.query_secdesc.in.file.fnum           = fnum;
1658                 fi.query_secdesc.in.secinfo_flags       = SECINFO_GROUP;
1659                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1660                 CHECK_STATUS_FOR_BIT(status, get_group_bits, SEC_STD_READ_CONTROL);
1661                 if (fi.query_secdesc.out.sd) {
1662                         sd_group = fi.query_secdesc.out.sd;
1663                 } else if (!sd_group) {
1664                         sd_group = sd;
1665                 }
1666                 si.set_secdesc.level                    = RAW_SFILEINFO_SEC_DESC;
1667                 si.set_secdesc.in.file.fnum             = fnum;
1668                 si.set_secdesc.in.secinfo_flags         = SECINFO_GROUP;
1669                 si.set_secdesc.in.sd                    = sd_group;
1670                 status = smb_raw_setfileinfo(cli->tree, &si);
1671                 CHECK_STATUS_FOR_BIT(status, set_group_bits, SEC_STD_WRITE_OWNER);
1672
1673                 /* test the DACL */
1674                 ZERO_STRUCT(fi);
1675                 fi.query_secdesc.level                  = RAW_FILEINFO_SEC_DESC;
1676                 fi.query_secdesc.in.file.fnum           = fnum;
1677                 fi.query_secdesc.in.secinfo_flags       = SECINFO_DACL;
1678                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1679                 CHECK_STATUS_FOR_BIT(status, get_dacl_bits, SEC_STD_READ_CONTROL);
1680                 if (fi.query_secdesc.out.sd) {
1681                         sd_dacl = fi.query_secdesc.out.sd;
1682                 } else if (!sd_dacl) {
1683                         sd_dacl = sd;
1684                 }
1685                 si.set_secdesc.level                    = RAW_SFILEINFO_SEC_DESC;
1686                 si.set_secdesc.in.file.fnum             = fnum;
1687                 si.set_secdesc.in.secinfo_flags         = SECINFO_DACL;
1688                 si.set_secdesc.in.sd                    = sd_dacl;
1689                 status = smb_raw_setfileinfo(cli->tree, &si);
1690                 CHECK_STATUS_FOR_BIT(status, set_dacl_bits, SEC_STD_WRITE_DAC);
1691
1692                 /* test the SACL */
1693                 ZERO_STRUCT(fi);
1694                 fi.query_secdesc.level                  = RAW_FILEINFO_SEC_DESC;
1695                 fi.query_secdesc.in.file.fnum           = fnum;
1696                 fi.query_secdesc.in.secinfo_flags       = SECINFO_SACL;
1697                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fi);
1698                 CHECK_STATUS_FOR_BIT(status, get_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
1699                 if (fi.query_secdesc.out.sd) {
1700                         sd_sacl = fi.query_secdesc.out.sd;
1701                 } else if (!sd_sacl) {
1702                         sd_sacl = sd;
1703                 }
1704                 si.set_secdesc.level                    = RAW_SFILEINFO_SEC_DESC;
1705                 si.set_secdesc.in.file.fnum             = fnum;
1706                 si.set_secdesc.in.secinfo_flags         = SECINFO_SACL;
1707                 si.set_secdesc.in.sd                    = sd_sacl;
1708                 status = smb_raw_setfileinfo(cli->tree, &si);
1709                 CHECK_STATUS_FOR_BIT(status, set_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
1710
1711                 /* close the handle */
1712                 status = smbcli_close(cli->tree, fnum);
1713                 CHECK_STATUS(status, NT_STATUS_OK);
1714 next:
1715                 continue;
1716         }
1717
1718 done:
1719         smbcli_close(cli->tree, fnum);
1720         smbcli_unlink(cli->tree, fname);
1721
1722         return ret;
1723 }
1724
1725
1726 /* 
1727    basic testing of security descriptor calls
1728 */
1729 BOOL torture_raw_acls(struct torture_context *torture)
1730 {
1731         struct smbcli_state *cli;
1732         BOOL ret = True;
1733         TALLOC_CTX *mem_ctx;
1734
1735         if (!torture_open_connection(&cli, 0)) {
1736                 return False;
1737         }
1738
1739         mem_ctx = talloc_init("torture_raw_acls");
1740
1741         if (!torture_setup_dir(cli, BASEDIR)) {
1742                 return False;
1743         }
1744
1745         ret &= test_sd(cli, mem_ctx);
1746         ret &= test_nttrans_create(cli, mem_ctx);
1747         ret &= test_creator_sid(cli, mem_ctx);
1748         ret &= test_generic_bits(cli, mem_ctx);
1749         ret &= test_owner_bits(cli, mem_ctx);
1750         ret &= test_inheritance(cli, mem_ctx);
1751         ret &= test_inheritance_dynamic(cli, mem_ctx);
1752         ret &= test_sd_get_set(cli, mem_ctx);
1753
1754         smb_raw_exit(cli->session);
1755         smbcli_deltree(cli->tree, BASEDIR);
1756
1757         torture_close_connection(cli);
1758         talloc_free(mem_ctx);
1759         return ret;
1760 }