s4-pvfs: fixed handling of SEC_FLAG_MAXIMUM_ALLOWED
[ira/wip.git] / source4 / ntvfs / posix / pvfs_acl.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - ACL support
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 "auth/auth.h"
24 #include "vfs_posix.h"
25 #include "librpc/gen_ndr/xattr.h"
26 #include "libcli/security/security.h"
27 #include "param/param.h"
28
29
30 /* the list of currently registered ACL backends */
31 static struct pvfs_acl_backend {
32         const struct pvfs_acl_ops *ops;
33 } *backends = NULL;
34 static int num_backends;
35
36 /*
37   register a pvfs acl backend. 
38
39   The 'name' can be later used by other backends to find the operations
40   structure for this backend.  
41 */
42 NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
43 {
44         struct pvfs_acl_ops *new_ops;
45
46         if (pvfs_acl_backend_byname(ops->name) != NULL) {
47                 DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
48                 return NT_STATUS_OBJECT_NAME_COLLISION;
49         }
50
51         backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
52         NT_STATUS_HAVE_NO_MEMORY(backends);
53
54         new_ops = (struct pvfs_acl_ops *)talloc_memdup(backends, ops, sizeof(*ops));
55         new_ops->name = talloc_strdup(new_ops, ops->name);
56
57         backends[num_backends].ops = new_ops;
58
59         num_backends++;
60
61         DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
62
63         return NT_STATUS_OK;
64 }
65
66
67 /*
68   return the operations structure for a named backend
69 */
70 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
71 {
72         int i;
73
74         for (i=0;i<num_backends;i++) {
75                 if (strcmp(backends[i].ops->name, name) == 0) {
76                         return backends[i].ops;
77                 }
78         }
79
80         return NULL;
81 }
82
83 NTSTATUS pvfs_acl_init(struct loadparm_context *lp_ctx)
84 {
85         static bool initialized = false;
86         extern NTSTATUS pvfs_acl_nfs4_init(void);
87         extern NTSTATUS pvfs_acl_xattr_init(void);
88         init_module_fn static_init[] = { STATIC_pvfs_acl_MODULES };
89         init_module_fn *shared_init;
90
91         if (initialized) return NT_STATUS_OK;
92         initialized = true;
93
94         shared_init = load_samba_modules(NULL, lp_ctx, "pvfs_acl");
95
96         run_init_functions(static_init);
97         run_init_functions(shared_init);
98
99         talloc_free(shared_init);
100
101         return NT_STATUS_OK;
102 }
103
104
105 /*
106   map a single access_mask from generic to specific bits for files/dirs
107 */
108 static uint32_t pvfs_translate_mask(uint32_t access_mask)
109 {
110         if (access_mask & SEC_MASK_GENERIC) {
111                 if (access_mask & SEC_GENERIC_READ)    access_mask |= SEC_RIGHTS_FILE_READ;
112                 if (access_mask & SEC_GENERIC_WRITE)   access_mask |= SEC_RIGHTS_FILE_WRITE;
113                 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
114                 if (access_mask & SEC_GENERIC_ALL)     access_mask |= SEC_RIGHTS_FILE_ALL;
115                 access_mask &= ~SEC_MASK_GENERIC;
116         }
117         return access_mask;
118 }
119
120
121 /*
122   map any generic access bits in the given acl
123   this relies on the fact that the mappings for files and directories
124   are the same
125 */
126 static void pvfs_translate_generic_bits(struct security_acl *acl)
127 {
128         unsigned i;
129
130         if (!acl) return;
131
132         for (i=0;i<acl->num_aces;i++) {
133                 struct security_ace *ace = &acl->aces[i];
134                 ace->access_mask = pvfs_translate_mask(ace->access_mask);
135         }
136 }
137
138
139 /*
140   setup a default ACL for a file
141 */
142 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
143                                  struct ntvfs_request *req,
144                                  struct pvfs_filename *name, int fd, 
145                                  struct security_descriptor **psd)
146 {
147         struct security_descriptor *sd;
148         NTSTATUS status;
149         struct security_ace ace;
150         mode_t mode;
151         struct id_mapping *ids;
152         struct composite_context *ctx;
153
154         *psd = security_descriptor_initialise(req);
155         if (*psd == NULL) {
156                 return NT_STATUS_NO_MEMORY;
157         }
158         sd = *psd;
159
160         ids = talloc_zero_array(sd, struct id_mapping, 2);
161         NT_STATUS_HAVE_NO_MEMORY(ids);
162
163         ids[0].unixid = talloc(ids, struct unixid);
164         NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
165
166         ids[0].unixid->id = name->st.st_uid;
167         ids[0].unixid->type = ID_TYPE_UID;
168         ids[0].sid = NULL;
169
170         ids[1].unixid = talloc(ids, struct unixid);
171         NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
172
173         ids[1].unixid->id = name->st.st_gid;
174         ids[1].unixid->type = ID_TYPE_GID;
175         ids[1].sid = NULL;
176
177         ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
178         NT_STATUS_HAVE_NO_MEMORY(ctx);
179
180         status = wbc_xids_to_sids_recv(ctx, &ids);
181         NT_STATUS_NOT_OK_RETURN(status);
182
183         sd->owner_sid = talloc_steal(sd, ids[0].sid);
184         sd->group_sid = talloc_steal(sd, ids[1].sid);
185
186         talloc_free(ids);
187         sd->type |= SEC_DESC_DACL_PRESENT;
188
189         mode = name->st.st_mode;
190
191         /*
192           we provide up to 4 ACEs
193             - Owner
194             - Group
195             - Everyone
196             - Administrator
197          */
198
199
200         /* setup owner ACE */
201         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
202         ace.flags = 0;
203         ace.trustee = *sd->owner_sid;
204         ace.access_mask = 0;
205
206         if (mode & S_IRUSR) {
207                 if (mode & S_IWUSR) {
208                         ace.access_mask |= SEC_RIGHTS_FILE_ALL;
209                 } else {
210                         ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
211                 }
212         }
213         if (mode & S_IWUSR) {
214                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
215         }
216         if (ace.access_mask) {
217                 security_descriptor_dacl_add(sd, &ace);
218         }
219
220
221         /* setup group ACE */
222         ace.trustee = *sd->group_sid;
223         ace.access_mask = 0;
224         if (mode & S_IRGRP) {
225                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
226         }
227         if (mode & S_IWGRP) {
228                 /* note that delete is not granted - this matches posix behaviour */
229                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
230         }
231         if (ace.access_mask) {
232                 security_descriptor_dacl_add(sd, &ace);
233         }
234
235         /* setup other ACE */
236         ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
237         ace.access_mask = 0;
238         if (mode & S_IROTH) {
239                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
240         }
241         if (mode & S_IWOTH) {
242                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
243         }
244         if (ace.access_mask) {
245                 security_descriptor_dacl_add(sd, &ace);
246         }
247
248         /* setup system ACE */
249         ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
250         ace.access_mask = SEC_RIGHTS_FILE_ALL;
251         security_descriptor_dacl_add(sd, &ace);
252         
253         return NT_STATUS_OK;
254 }
255                                  
256
257 /*
258   omit any security_descriptor elements not specified in the given
259   secinfo flags
260 */
261 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
262 {
263         if (!(secinfo_flags & SECINFO_OWNER)) {
264                 sd->owner_sid = NULL;
265         }
266         if (!(secinfo_flags & SECINFO_GROUP)) {
267                 sd->group_sid = NULL;
268         }
269         if (!(secinfo_flags & SECINFO_DACL)) {
270                 sd->dacl = NULL;
271         }
272         if (!(secinfo_flags & SECINFO_SACL)) {
273                 sd->sacl = NULL;
274         }
275 }
276
277 /*
278   answer a setfileinfo for an ACL
279 */
280 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, 
281                       struct ntvfs_request *req,
282                       struct pvfs_filename *name, int fd, 
283                       uint32_t access_mask,
284                       union smb_setfileinfo *info)
285 {
286         uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
287         struct security_descriptor *new_sd, *sd, orig_sd;
288         NTSTATUS status = NT_STATUS_NOT_FOUND;
289         uid_t old_uid = -1;
290         gid_t old_gid = -1;
291         uid_t new_uid = -1;
292         gid_t new_gid = -1;
293         struct id_mapping *ids;
294         struct composite_context *ctx;
295
296         if (pvfs->acl_ops != NULL) {
297                 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
298         }
299         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
300                 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
301         }
302         if (!NT_STATUS_IS_OK(status)) {
303                 return status;
304         }
305
306         ids = talloc(req, struct id_mapping);
307         NT_STATUS_HAVE_NO_MEMORY(ids);
308         ids->unixid = NULL;
309         ids->sid = NULL;
310         ids->status = NT_STATUS_NONE_MAPPED;
311
312         new_sd = info->set_secdesc.in.sd;
313         orig_sd = *sd;
314
315         old_uid = name->st.st_uid;
316         old_gid = name->st.st_gid;
317
318         /* only set the elements that have been specified */
319         if (secinfo_flags & SECINFO_OWNER) {
320                 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
321                         return NT_STATUS_ACCESS_DENIED;
322                 }
323                 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
324                         ids->sid = new_sd->owner_sid;
325                         ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
326                         NT_STATUS_HAVE_NO_MEMORY(ctx);
327                         status = wbc_sids_to_xids_recv(ctx, &ids);
328                         NT_STATUS_NOT_OK_RETURN(status);
329
330                         if (ids->unixid->type == ID_TYPE_BOTH ||
331                             ids->unixid->type == ID_TYPE_UID) {
332                                 new_uid = ids->unixid->id;
333                         }
334                 }
335                 sd->owner_sid = new_sd->owner_sid;
336         }
337         if (secinfo_flags & SECINFO_GROUP) {
338                 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
339                         return NT_STATUS_ACCESS_DENIED;
340                 }
341                 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
342                         ids->sid = new_sd->group_sid;
343                         ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
344                         NT_STATUS_HAVE_NO_MEMORY(ctx);
345                         status = wbc_sids_to_xids_recv(ctx, &ids);
346                         NT_STATUS_NOT_OK_RETURN(status);
347
348                         if (ids->unixid->type == ID_TYPE_BOTH ||
349                             ids->unixid->type == ID_TYPE_GID) {
350                                 new_gid = ids->unixid->id;
351                         }
352
353                 }
354                 sd->group_sid = new_sd->group_sid;
355         }
356         if (secinfo_flags & SECINFO_DACL) {
357                 if (!(access_mask & SEC_STD_WRITE_DAC)) {
358                         return NT_STATUS_ACCESS_DENIED;
359                 }
360                 sd->dacl = new_sd->dacl;
361                 pvfs_translate_generic_bits(sd->dacl);
362         }
363         if (secinfo_flags & SECINFO_SACL) {
364                 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
365                         return NT_STATUS_ACCESS_DENIED;
366                 }
367                 sd->sacl = new_sd->sacl;
368                 pvfs_translate_generic_bits(sd->sacl);
369         }
370
371         if (new_uid == old_uid) {
372                 new_uid = -1;
373         }
374
375         if (new_gid == old_gid) {
376                 new_gid = -1;
377         }
378
379         /* if there's something to change try it */
380         if (new_uid != -1 || new_gid != -1) {
381                 int ret;
382                 if (fd == -1) {
383                         ret = chown(name->full_name, new_uid, new_gid);
384                 } else {
385                         ret = fchown(fd, new_uid, new_gid);
386                 }
387                 if (ret == -1) {
388                         return pvfs_map_errno(pvfs, errno);
389                 }
390         }
391
392         /* we avoid saving if the sd is the same. This means when clients
393            copy files and end up copying the default sd that we don't
394            needlessly use xattrs */
395         if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
396                 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
397         }
398
399         return status;
400 }
401
402
403 /*
404   answer a fileinfo query for the ACL
405 */
406 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
407                         struct ntvfs_request *req,
408                         struct pvfs_filename *name, int fd, 
409                         union smb_fileinfo *info)
410 {
411         NTSTATUS status = NT_STATUS_NOT_FOUND;
412         struct security_descriptor *sd;
413
414         if (pvfs->acl_ops) {
415                 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
416         }
417         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
418                 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
419         }
420         if (!NT_STATUS_IS_OK(status)) {
421                 return status;
422         }
423
424         normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
425
426         info->query_secdesc.out.sd = sd;
427
428         return NT_STATUS_OK;
429 }
430
431
432 /*
433   check the read only bit against any of the write access bits
434 */
435 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
436 {
437         if ((pvfs->flags & PVFS_FLAG_READONLY) &&
438             (access_mask & (SEC_FILE_WRITE_DATA |
439                             SEC_FILE_APPEND_DATA | 
440                             SEC_FILE_WRITE_EA | 
441                             SEC_FILE_WRITE_ATTRIBUTE | 
442                             SEC_STD_DELETE | 
443                             SEC_STD_WRITE_DAC | 
444                             SEC_STD_WRITE_OWNER | 
445                             SEC_DIR_DELETE_CHILD))) {
446                 return true;
447         }
448         return false;
449 }
450
451 /*
452   see if we are a member of the appropriate unix group
453  */
454 static bool pvfs_group_member(struct pvfs_state *pvfs, gid_t gid)
455 {
456         int i, ngroups;
457         gid_t *groups;
458         if (getegid() == gid) {
459                 return true;
460         }
461         ngroups = getgroups(0, NULL);
462         if (ngroups == 0) {
463                 return false;
464         }
465         groups = talloc_array(pvfs, gid_t, ngroups);
466         if (groups == NULL) {
467                 return false;
468         }
469         if (getgroups(ngroups, groups) != ngroups) {
470                 talloc_free(groups);
471                 return false;
472         }
473         for (i=0; i<ngroups; i++) {
474                 if (groups[i] == gid) break;
475         }
476         talloc_free(groups);
477         return i < ngroups;
478 }
479
480 /*
481   default access check function based on unix permissions
482   doing this saves on building a full security descriptor
483   for the common case of access check on files with no 
484   specific NT ACL
485 */
486 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
487                                 struct ntvfs_request *req,
488                                 struct pvfs_filename *name,
489                                 uint32_t *access_mask)
490 {
491         uid_t uid = geteuid();
492         uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
493
494         if (pvfs_read_only(pvfs, *access_mask)) {
495                 return NT_STATUS_ACCESS_DENIED;
496         }
497
498         /* owner and root get extra permissions */
499         if (uid == 0) {
500                 max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
501         } else if (uid == name->st.st_uid) {
502                 max_bits |= SEC_STD_ALL;
503         }
504
505         if ((name->st.st_mode & S_IWOTH) ||
506             ((name->st.st_mode & S_IWGRP) && 
507              pvfs_group_member(pvfs, name->st.st_gid))) {
508                 max_bits |= SEC_STD_ALL;
509         }
510
511         if (uwrap_enabled()) {
512                 /* when running with the uid wrapper, files will be created
513                    owned by the ruid, but we may have a different simulated 
514                    euid. We need to force the permission bits as though the 
515                    files owner matches the euid */
516                 max_bits |= SEC_STD_ALL;
517         }
518
519         if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
520                 *access_mask = max_bits;
521                 return NT_STATUS_OK;
522         }
523
524         if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
525                 return NT_STATUS_ACCESS_DENIED;
526         }
527
528         if (*access_mask & ~max_bits) {
529                 DEBUG(0,(__location__ " denied access to '%s' - wanted 0x%08x but got 0x%08x (missing 0x%08x)\n",
530                          name->full_name, *access_mask, max_bits, *access_mask & ~max_bits));
531                 return NT_STATUS_ACCESS_DENIED;
532         }
533
534         if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
535                 /* on SMB, this bit is always granted, even if not
536                    asked for */
537                 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
538         }
539
540         return NT_STATUS_OK;
541 }
542
543
544 /*
545   check the security descriptor on a file, if any
546   
547   *access_mask is modified with the access actually granted
548 */
549 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
550                            struct ntvfs_request *req,
551                            struct pvfs_filename *name,
552                            uint32_t *access_mask)
553 {
554         struct security_token *token = req->session_info->security_token;
555         struct xattr_NTACL *acl;
556         NTSTATUS status;
557         struct security_descriptor *sd;
558
559         /* on SMB2 a blank access mask is always denied */
560         if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2 &&
561             *access_mask == 0) {
562                 return NT_STATUS_ACCESS_DENIED;
563         }
564
565         if (pvfs_read_only(pvfs, *access_mask)) {
566                 return NT_STATUS_ACCESS_DENIED;
567         }
568
569         acl = talloc(req, struct xattr_NTACL);
570         if (acl == NULL) {
571                 return NT_STATUS_NO_MEMORY;
572         }
573
574         /* expand the generic access bits to file specific bits */
575         *access_mask = pvfs_translate_mask(*access_mask);
576         if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
577                 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
578         }
579
580         status = pvfs_acl_load(pvfs, name, -1, acl);
581         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
582                 talloc_free(acl);
583                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
584         }
585         if (!NT_STATUS_IS_OK(status)) {
586                 return status;
587         }
588
589         switch (acl->version) {
590         case 1:
591                 sd = acl->info.sd;
592                 break;
593         default:
594                 return NT_STATUS_INVALID_ACL;
595         }
596
597         /* check the acl against the required access mask */
598         status = sec_access_check(sd, token, *access_mask, access_mask);
599
600         if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
601                 /* on SMB, this bit is always granted, even if not
602                    asked for */
603                 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
604         }
605
606         talloc_free(acl);
607         
608         return status;
609 }
610
611
612 /*
613   a simplified interface to access check, designed for calls that
614   do not take or return an access check mask
615 */
616 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
617                                   struct ntvfs_request *req,
618                                   struct pvfs_filename *name,
619                                   uint32_t access_needed)
620 {
621         if (access_needed == 0) {
622                 return NT_STATUS_OK;
623         }
624         return pvfs_access_check(pvfs, req, name, &access_needed);
625 }
626
627 /*
628   access check for creating a new file/directory
629 */
630 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
631                                   struct ntvfs_request *req,
632                                   struct pvfs_filename *name,
633                                   uint32_t *access_mask)
634 {
635         struct pvfs_filename *parent;
636         NTSTATUS status;
637
638         status = pvfs_resolve_parent(pvfs, req, name, &parent);
639         if (!NT_STATUS_IS_OK(status)) {
640                 return status;
641         }
642
643         status = pvfs_access_check(pvfs, req, parent, access_mask);
644         if (!NT_STATUS_IS_OK(status)) {
645                 return status;
646         }
647
648         if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
649                 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
650         }
651
652         return status;
653 }
654
655 /*
656   access check for creating a new file/directory - no access mask supplied
657 */
658 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs, 
659                                   struct ntvfs_request *req,
660                                   struct pvfs_filename *name,
661                                   uint32_t access_mask)
662 {
663         struct pvfs_filename *parent;
664         NTSTATUS status;
665
666         status = pvfs_resolve_parent(pvfs, req, name, &parent);
667         if (!NT_STATUS_IS_OK(status)) {
668                 return status;
669         }
670
671         return pvfs_access_check_simple(pvfs, req, parent, access_mask);
672 }
673
674
675 /*
676   determine if an ACE is inheritable
677 */
678 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
679                                  const struct security_ace *ace,
680                                  bool container)
681 {
682         if (!container) {
683                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
684         }
685
686         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
687                 return true;
688         }
689
690         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
691             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
692                 return true;
693         }
694
695         return false;
696 }
697
698 /*
699   this is the core of ACL inheritance. It copies any inheritable
700   aces from the parent SD to the child SD. Note that the algorithm 
701   depends on whether the child is a container or not
702 */
703 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
704                                       struct security_descriptor *parent_sd,
705                                       struct security_descriptor *sd,
706                                       bool container)
707 {
708         int i;
709         
710         for (i=0;i<parent_sd->dacl->num_aces;i++) {
711                 struct security_ace ace = parent_sd->dacl->aces[i];
712                 NTSTATUS status;
713                 const struct dom_sid *creator = NULL, *new_id = NULL;
714                 uint32_t orig_flags;
715
716                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
717                         continue;
718                 }
719
720                 orig_flags = ace.flags;
721
722                 /* see the RAW-ACLS inheritance test for details on these rules */
723                 if (!container) {
724                         ace.flags = 0;
725                 } else {
726                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
727
728                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
729                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
730                         }
731                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
732                                 ace.flags = 0;
733                         }
734                 }
735
736                 /* the CREATOR sids are special when inherited */
737                 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
738                         creator = pvfs->sid_cache.creator_owner;
739                         new_id = sd->owner_sid;
740                 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
741                         creator = pvfs->sid_cache.creator_group;
742                         new_id = sd->group_sid;
743                 } else {
744                         new_id = &ace.trustee;
745                 }
746
747                 if (creator && container && 
748                     (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
749                         uint32_t flags = ace.flags;
750
751                         ace.trustee = *new_id;
752                         ace.flags = 0;
753                         status = security_descriptor_dacl_add(sd, &ace);
754                         if (!NT_STATUS_IS_OK(status)) {
755                                 return status;
756                         }
757
758                         ace.trustee = *creator;
759                         ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
760                         status = security_descriptor_dacl_add(sd, &ace);
761                 } else if (container && 
762                            !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
763                         status = security_descriptor_dacl_add(sd, &ace);
764                 } else {
765                         ace.trustee = *new_id;
766                         status = security_descriptor_dacl_add(sd, &ace);
767                 }
768
769                 if (!NT_STATUS_IS_OK(status)) {
770                         return status;
771                 }
772         }
773
774         return NT_STATUS_OK;
775 }
776
777
778
779 /*
780   setup an ACL on a new file/directory based on the inherited ACL from
781   the parent. If there is no inherited ACL then we don't set anything,
782   as the default ACL applies anyway
783 */
784 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
785                           struct ntvfs_request *req,
786                           struct pvfs_filename *name,
787                           int fd)
788 {
789         struct xattr_NTACL *acl;
790         NTSTATUS status;
791         struct pvfs_filename *parent;
792         struct security_descriptor *parent_sd, *sd;
793         bool container;
794         struct id_mapping *ids;
795         struct composite_context *ctx;
796
797         /* form the parents path */
798         status = pvfs_resolve_parent(pvfs, req, name, &parent);
799         if (!NT_STATUS_IS_OK(status)) {
800                 return status;
801         }
802
803         acl = talloc(req, struct xattr_NTACL);
804         if (acl == NULL) {
805                 return NT_STATUS_NO_MEMORY;
806         }
807
808         status = pvfs_acl_load(pvfs, parent, -1, acl);
809         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
810                 return NT_STATUS_OK;
811         }
812         if (!NT_STATUS_IS_OK(status)) {
813                 return status;
814         }
815
816         switch (acl->version) {
817         case 1:
818                 parent_sd = acl->info.sd;
819                 break;
820         default:
821                 return NT_STATUS_INVALID_ACL;
822         }
823
824         if (parent_sd == NULL ||
825             parent_sd->dacl == NULL ||
826             parent_sd->dacl->num_aces == 0) {
827                 /* go with the default ACL */
828                 return NT_STATUS_OK;
829         }
830
831         /* create the new sd */
832         sd = security_descriptor_initialise(req);
833         if (sd == NULL) {
834                 return NT_STATUS_NO_MEMORY;
835         }
836
837         ids = talloc_array(sd, struct id_mapping, 2);
838         NT_STATUS_HAVE_NO_MEMORY(ids);
839
840         ids[0].unixid = talloc(ids, struct unixid);
841         NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
842         ids[0].unixid->id = name->st.st_uid;
843         ids[0].unixid->type = ID_TYPE_UID;
844         ids[0].sid = NULL;
845         ids[0].status = NT_STATUS_NONE_MAPPED;
846
847         ids[1].unixid = talloc(ids, struct unixid);
848         NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
849         ids[1].unixid->id = name->st.st_gid;
850         ids[1].unixid->type = ID_TYPE_GID;
851         ids[1].sid = NULL;
852         ids[1].status = NT_STATUS_NONE_MAPPED;
853
854         ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
855         NT_STATUS_HAVE_NO_MEMORY(ctx);
856
857         status = wbc_xids_to_sids_recv(ctx, &ids);
858         NT_STATUS_NOT_OK_RETURN(status);
859
860         sd->owner_sid = talloc_steal(sd, ids[0].sid);
861         sd->group_sid = talloc_steal(sd, ids[1].sid);
862
863         sd->type |= SEC_DESC_DACL_PRESENT;
864
865         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
866
867         /* fill in the aces from the parent */
868         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
869         if (!NT_STATUS_IS_OK(status)) {
870                 return status;
871         }
872
873         /* if there is nothing to inherit then we fallback to the
874            default acl */
875         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
876                 return NT_STATUS_OK;
877         }
878
879         acl->info.sd = sd;
880
881         status = pvfs_acl_save(pvfs, name, fd, acl);
882         
883         return status;
884 }
885
886 /*
887   return the maximum allowed access mask
888 */
889 NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs, 
890                                      struct ntvfs_request *req,
891                                      struct pvfs_filename *name,
892                                      uint32_t *maximal_access)
893 {
894         *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
895         return pvfs_access_check(pvfs, req, name, maximal_access);
896 }