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