f1e469f7909fdb9b8b394cd36687fea606fa844f
[kai/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_PRIVILEGE_NOT_HELD;
461         }
462
463         if (*access_mask & ~max_bits) {
464                 return NT_STATUS_ACCESS_DENIED;
465         }
466
467         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
468
469         return NT_STATUS_OK;
470 }
471
472
473 /*
474   check the security descriptor on a file, if any
475   
476   *access_mask is modified with the access actually granted
477 */
478 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
479                            struct ntvfs_request *req,
480                            struct pvfs_filename *name,
481                            uint32_t *access_mask)
482 {
483         struct security_token *token = req->session_info->security_token;
484         struct xattr_NTACL *acl;
485         NTSTATUS status;
486         struct security_descriptor *sd;
487
488         if (pvfs_read_only(pvfs, *access_mask)) {
489                 return NT_STATUS_ACCESS_DENIED;
490         }
491
492         acl = talloc(req, struct xattr_NTACL);
493         if (acl == NULL) {
494                 return NT_STATUS_NO_MEMORY;
495         }
496
497         /* expand the generic access bits to file specific bits */
498         *access_mask = pvfs_translate_mask(*access_mask);
499         *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
500
501         status = pvfs_acl_load(pvfs, name, -1, acl);
502         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
503                 talloc_free(acl);
504                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
505         }
506         if (!NT_STATUS_IS_OK(status)) {
507                 return status;
508         }
509
510         switch (acl->version) {
511         case 1:
512                 sd = acl->info.sd;
513                 break;
514         default:
515                 return NT_STATUS_INVALID_ACL;
516         }
517
518         /* check the acl against the required access mask */
519         status = sec_access_check(sd, token, *access_mask, access_mask);
520
521         /* this bit is always granted, even if not asked for */
522         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
523
524         talloc_free(acl);
525         
526         return status;
527 }
528
529
530 /*
531   a simplified interface to access check, designed for calls that
532   do not take or return an access check mask
533 */
534 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
535                                   struct ntvfs_request *req,
536                                   struct pvfs_filename *name,
537                                   uint32_t access_needed)
538 {
539         if (access_needed == 0) {
540                 return NT_STATUS_OK;
541         }
542         return pvfs_access_check(pvfs, req, name, &access_needed);
543 }
544
545 /*
546   access check for creating a new file/directory
547 */
548 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
549                                   struct ntvfs_request *req,
550                                   struct pvfs_filename *name,
551                                   uint32_t *access_mask)
552 {
553         struct pvfs_filename *parent;
554         NTSTATUS status;
555
556         status = pvfs_resolve_parent(pvfs, req, name, &parent);
557         if (!NT_STATUS_IS_OK(status)) {
558                 return status;
559         }
560
561         status = pvfs_access_check(pvfs, req, parent, access_mask);
562         if (!NT_STATUS_IS_OK(status)) {
563                 return status;
564         }
565
566         if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
567                 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
568         }
569
570         return status;
571 }
572
573 /*
574   access check for creating a new file/directory - no access mask supplied
575 */
576 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs, 
577                                   struct ntvfs_request *req,
578                                   struct pvfs_filename *name,
579                                   uint32_t access_mask)
580 {
581         struct pvfs_filename *parent;
582         NTSTATUS status;
583
584         status = pvfs_resolve_parent(pvfs, req, name, &parent);
585         if (!NT_STATUS_IS_OK(status)) {
586                 return status;
587         }
588
589         return pvfs_access_check_simple(pvfs, req, parent, access_mask);
590 }
591
592
593 /*
594   determine if an ACE is inheritable
595 */
596 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
597                                  const struct security_ace *ace,
598                                  bool container)
599 {
600         if (!container) {
601                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
602         }
603
604         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
605                 return true;
606         }
607
608         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
609             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
610                 return true;
611         }
612
613         return false;
614 }
615
616 /*
617   this is the core of ACL inheritance. It copies any inheritable
618   aces from the parent SD to the child SD. Note that the algorithm 
619   depends on whether the child is a container or not
620 */
621 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
622                                       struct security_descriptor *parent_sd,
623                                       struct security_descriptor *sd,
624                                       bool container)
625 {
626         int i;
627         
628         for (i=0;i<parent_sd->dacl->num_aces;i++) {
629                 struct security_ace ace = parent_sd->dacl->aces[i];
630                 NTSTATUS status;
631                 const struct dom_sid *creator = NULL, *new_id = NULL;
632                 uint32_t orig_flags;
633
634                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
635                         continue;
636                 }
637
638                 orig_flags = ace.flags;
639
640                 /* see the RAW-ACLS inheritance test for details on these rules */
641                 if (!container) {
642                         ace.flags = 0;
643                 } else {
644                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
645
646                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
647                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
648                         }
649                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
650                                 ace.flags = 0;
651                         }
652                 }
653
654                 /* the CREATOR sids are special when inherited */
655                 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
656                         creator = pvfs->sid_cache.creator_owner;
657                         new_id = sd->owner_sid;
658                 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
659                         creator = pvfs->sid_cache.creator_group;
660                         new_id = sd->group_sid;
661                 } else {
662                         new_id = &ace.trustee;
663                 }
664
665                 if (creator && container && 
666                     (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
667                         uint32_t flags = ace.flags;
668
669                         ace.trustee = *new_id;
670                         ace.flags = 0;
671                         status = security_descriptor_dacl_add(sd, &ace);
672                         if (!NT_STATUS_IS_OK(status)) {
673                                 return status;
674                         }
675
676                         ace.trustee = *creator;
677                         ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
678                         status = security_descriptor_dacl_add(sd, &ace);
679                 } else if (container && 
680                            !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
681                         status = security_descriptor_dacl_add(sd, &ace);
682                 } else {
683                         ace.trustee = *new_id;
684                         status = security_descriptor_dacl_add(sd, &ace);
685                 }
686
687                 if (!NT_STATUS_IS_OK(status)) {
688                         return status;
689                 }
690         }
691
692         return NT_STATUS_OK;
693 }
694
695
696
697 /*
698   setup an ACL on a new file/directory based on the inherited ACL from
699   the parent. If there is no inherited ACL then we don't set anything,
700   as the default ACL applies anyway
701 */
702 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
703                           struct ntvfs_request *req,
704                           struct pvfs_filename *name,
705                           int fd)
706 {
707         struct xattr_NTACL *acl;
708         NTSTATUS status;
709         struct pvfs_filename *parent;
710         struct security_descriptor *parent_sd, *sd;
711         bool container;
712         struct id_mapping *ids;
713         struct composite_context *ctx;
714
715         /* form the parents path */
716         status = pvfs_resolve_parent(pvfs, req, name, &parent);
717         if (!NT_STATUS_IS_OK(status)) {
718                 return status;
719         }
720
721         acl = talloc(req, struct xattr_NTACL);
722         if (acl == NULL) {
723                 return NT_STATUS_NO_MEMORY;
724         }
725
726         status = pvfs_acl_load(pvfs, parent, -1, acl);
727         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
728                 return NT_STATUS_OK;
729         }
730         if (!NT_STATUS_IS_OK(status)) {
731                 return status;
732         }
733
734         switch (acl->version) {
735         case 1:
736                 parent_sd = acl->info.sd;
737                 break;
738         default:
739                 return NT_STATUS_INVALID_ACL;
740         }
741
742         if (parent_sd == NULL ||
743             parent_sd->dacl == NULL ||
744             parent_sd->dacl->num_aces == 0) {
745                 /* go with the default ACL */
746                 return NT_STATUS_OK;
747         }
748
749         /* create the new sd */
750         sd = security_descriptor_initialise(req);
751         if (sd == NULL) {
752                 return NT_STATUS_NO_MEMORY;
753         }
754
755         ids = talloc_array(sd, struct id_mapping, 2);
756         NT_STATUS_HAVE_NO_MEMORY(ids);
757
758         ids[0].unixid = talloc(ids, struct unixid);
759         NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
760         ids[0].unixid->id = name->st.st_uid;
761         ids[0].unixid->type = ID_TYPE_UID;
762         ids[0].sid = NULL;
763         ids[0].status = NT_STATUS_NONE_MAPPED;
764
765         ids[1].unixid = talloc(ids, struct unixid);
766         NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
767         ids[1].unixid->id = name->st.st_gid;
768         ids[1].unixid->type = ID_TYPE_GID;
769         ids[1].sid = NULL;
770         ids[1].status = NT_STATUS_NONE_MAPPED;
771
772         ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
773         NT_STATUS_HAVE_NO_MEMORY(ctx);
774
775         status = wbc_xids_to_sids_recv(ctx, &ids);
776         NT_STATUS_NOT_OK_RETURN(status);
777
778         sd->owner_sid = talloc_steal(sd, ids[0].sid);
779         sd->group_sid = talloc_steal(sd, ids[1].sid);
780
781         sd->type |= SEC_DESC_DACL_PRESENT;
782
783         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
784
785         /* fill in the aces from the parent */
786         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
787         if (!NT_STATUS_IS_OK(status)) {
788                 return status;
789         }
790
791         /* if there is nothing to inherit then we fallback to the
792            default acl */
793         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
794                 return NT_STATUS_OK;
795         }
796
797         acl->info.sd = sd;
798
799         status = pvfs_acl_save(pvfs, name, fd, acl);
800         
801         return status;
802 }