1a3fc184def1fbe667550b0d77b679833f62774e
[metze/samba/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 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "vfs_posix.h"
26 #include "librpc/gen_ndr/xattr.h"
27 #include "libcli/security/security.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 _PUBLIC_ 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 = 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 _PUBLIC_ 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
84 /*
85   map a single access_mask from generic to specific bits for files/dirs
86 */
87 static uint32_t pvfs_translate_mask(uint32_t access_mask)
88 {
89         if (access_mask & SEC_MASK_GENERIC) {
90                 if (access_mask & SEC_GENERIC_READ)    access_mask |= SEC_RIGHTS_FILE_READ;
91                 if (access_mask & SEC_GENERIC_WRITE)   access_mask |= SEC_RIGHTS_FILE_WRITE;
92                 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
93                 if (access_mask & SEC_GENERIC_ALL)     access_mask |= SEC_RIGHTS_FILE_ALL;
94                 access_mask &= ~SEC_MASK_GENERIC;
95         }
96         return access_mask;
97 }
98
99
100 /*
101   map any generic access bits in the given acl
102   this relies on the fact that the mappings for files and directories
103   are the same
104 */
105 static void pvfs_translate_generic_bits(struct security_acl *acl)
106 {
107         unsigned i;
108
109         if (!acl) return;
110
111         for (i=0;i<acl->num_aces;i++) {
112                 struct security_ace *ace = &acl->aces[i];
113                 ace->access_mask = pvfs_translate_mask(ace->access_mask);
114         }
115 }
116
117
118 /*
119   setup a default ACL for a file
120 */
121 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
122                                  struct ntvfs_request *req,
123                                  struct pvfs_filename *name, int fd, 
124                                  struct security_descriptor **psd)
125 {
126         struct security_descriptor *sd;
127         NTSTATUS status;
128         struct security_ace ace;
129         mode_t mode;
130
131         *psd = security_descriptor_initialise(req);
132         if (*psd == NULL) {
133                 return NT_STATUS_NO_MEMORY;
134         }
135         sd = *psd;
136
137         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
138         if (!NT_STATUS_IS_OK(status)) {
139                 return status;
140         }
141         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
142         if (!NT_STATUS_IS_OK(status)) {
143                 return status;
144         }
145
146         sd->type |= SEC_DESC_DACL_PRESENT;
147
148         mode = name->st.st_mode;
149
150         /*
151           we provide up to 4 ACEs
152             - Owner
153             - Group
154             - Everyone
155             - Administrator
156          */
157
158
159         /* setup owner ACE */
160         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
161         ace.flags = 0;
162         ace.trustee = *sd->owner_sid;
163         ace.access_mask = 0;
164
165         if (mode & S_IRUSR) {
166                 if (mode & S_IWUSR) {
167                         ace.access_mask |= SEC_RIGHTS_FILE_ALL;
168                 } else {
169                         ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
170                 }
171         }
172         if (mode & S_IWUSR) {
173                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
174         }
175         if (ace.access_mask) {
176                 security_descriptor_dacl_add(sd, &ace);
177         }
178
179
180         /* setup group ACE */
181         ace.trustee = *sd->group_sid;
182         ace.access_mask = 0;
183         if (mode & S_IRGRP) {
184                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
185         }
186         if (mode & S_IWGRP) {
187                 /* note that delete is not granted - this matches posix behaviour */
188                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
189         }
190         if (ace.access_mask) {
191                 security_descriptor_dacl_add(sd, &ace);
192         }
193
194         /* setup other ACE */
195         ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
196         ace.access_mask = 0;
197         if (mode & S_IROTH) {
198                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
199         }
200         if (mode & S_IWOTH) {
201                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
202         }
203         if (ace.access_mask) {
204                 security_descriptor_dacl_add(sd, &ace);
205         }
206
207         /* setup system ACE */
208         ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
209         ace.access_mask = SEC_RIGHTS_FILE_ALL;
210         security_descriptor_dacl_add(sd, &ace);
211         
212         return NT_STATUS_OK;
213 }
214                                  
215
216 /*
217   omit any security_descriptor elements not specified in the given
218   secinfo flags
219 */
220 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
221 {
222         if (!(secinfo_flags & SECINFO_OWNER)) {
223                 sd->owner_sid = NULL;
224         }
225         if (!(secinfo_flags & SECINFO_GROUP)) {
226                 sd->group_sid = NULL;
227         }
228         if (!(secinfo_flags & SECINFO_DACL)) {
229                 sd->dacl = NULL;
230         }
231         if (!(secinfo_flags & SECINFO_SACL)) {
232                 sd->sacl = NULL;
233         }
234 }
235
236 /*
237   answer a setfileinfo for an ACL
238 */
239 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, 
240                       struct ntvfs_request *req,
241                       struct pvfs_filename *name, int fd, 
242                       uint32_t access_mask,
243                       union smb_setfileinfo *info)
244 {
245         uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
246         struct security_descriptor *new_sd, *sd, orig_sd;
247         NTSTATUS status = NT_STATUS_NOT_FOUND;
248         uid_t old_uid = -1;
249         gid_t old_gid = -1;
250         uid_t new_uid = -1;
251         gid_t new_gid = -1;
252
253         if (pvfs->acl_ops != NULL) {
254                 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
255         }
256         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
257                 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
258         }
259         if (!NT_STATUS_IS_OK(status)) {
260                 return status;
261         }
262
263         new_sd = info->set_secdesc.in.sd;
264         orig_sd = *sd;
265
266         old_uid = name->st.st_uid;
267         old_gid = name->st.st_gid;
268
269         /* only set the elements that have been specified */
270         if (secinfo_flags & SECINFO_OWNER) {
271                 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
272                         return NT_STATUS_ACCESS_DENIED;
273                 }
274                 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
275                         status = sidmap_sid_to_unixuid(pvfs->sidmap, new_sd->owner_sid, &new_uid);
276                         NT_STATUS_NOT_OK_RETURN(status);
277                 }
278                 sd->owner_sid = new_sd->owner_sid;
279         }
280         if (secinfo_flags & SECINFO_GROUP) {
281                 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
282                         return NT_STATUS_ACCESS_DENIED;
283                 }
284                 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
285                         status = sidmap_sid_to_unixgid(pvfs->sidmap, new_sd->group_sid, &new_gid);
286                         NT_STATUS_NOT_OK_RETURN(status);
287                 }
288                 sd->group_sid = new_sd->group_sid;
289         }
290         if (secinfo_flags & SECINFO_DACL) {
291                 if (!(access_mask & SEC_STD_WRITE_DAC)) {
292                         return NT_STATUS_ACCESS_DENIED;
293                 }
294                 sd->dacl = new_sd->dacl;
295                 pvfs_translate_generic_bits(sd->dacl);
296         }
297         if (secinfo_flags & SECINFO_SACL) {
298                 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
299                         return NT_STATUS_ACCESS_DENIED;
300                 }
301                 sd->sacl = new_sd->sacl;
302                 pvfs_translate_generic_bits(sd->sacl);
303         }
304
305         if (new_uid == old_uid) {
306                 new_uid = -1;
307         }
308
309         if (new_gid == old_gid) {
310                 new_gid = -1;
311         }
312
313         /* if there's something to change try it */
314         if (new_uid != -1 || new_gid != -1) {
315                 int ret;
316                 if (fd == -1) {
317                         ret = chown(name->full_name, new_uid, new_gid);
318                 } else {
319                         ret = fchown(fd, new_uid, new_gid);
320                 }
321                 if (ret == -1) {
322                         return pvfs_map_errno(pvfs, errno);
323                 }
324         }
325
326         /* we avoid saving if the sd is the same. This means when clients
327            copy files and end up copying the default sd that we don't
328            needlessly use xattrs */
329         if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
330                 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
331         }
332
333         return status;
334 }
335
336
337 /*
338   answer a fileinfo query for the ACL
339 */
340 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
341                         struct ntvfs_request *req,
342                         struct pvfs_filename *name, int fd, 
343                         union smb_fileinfo *info)
344 {
345         NTSTATUS status = NT_STATUS_NOT_FOUND;
346         struct security_descriptor *sd;
347
348         if (pvfs->acl_ops) {
349                 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
350         }
351         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
352                 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
353         }
354         if (!NT_STATUS_IS_OK(status)) {
355                 return status;
356         }
357
358         normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
359
360         info->query_secdesc.out.sd = sd;
361
362         return NT_STATUS_OK;
363 }
364
365
366 /*
367   check the read only bit against any of the write access bits
368 */
369 static BOOL pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
370 {
371         if ((pvfs->flags & PVFS_FLAG_READONLY) &&
372             (access_mask & (SEC_FILE_WRITE_DATA |
373                             SEC_FILE_APPEND_DATA | 
374                             SEC_FILE_WRITE_EA | 
375                             SEC_FILE_WRITE_ATTRIBUTE | 
376                             SEC_STD_DELETE | 
377                             SEC_STD_WRITE_DAC | 
378                             SEC_STD_WRITE_OWNER | 
379                             SEC_DIR_DELETE_CHILD))) {
380                 return True;
381         }
382         return False;
383 }
384
385 /*
386   default access check function based on unix permissions
387   doing this saves on building a full security descriptor
388   for the common case of access check on files with no 
389   specific NT ACL
390 */
391 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
392                                 struct ntvfs_request *req,
393                                 struct pvfs_filename *name,
394                                 uint32_t *access_mask)
395 {
396         uid_t uid = geteuid();
397         uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
398
399         if (pvfs_read_only(pvfs, *access_mask)) {
400                 return NT_STATUS_ACCESS_DENIED;
401         }
402
403         /* owner and root get extra permissions */
404         if (uid == 0) {
405                 max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
406         } else if (uid == name->st.st_uid) {
407                 max_bits |= SEC_STD_ALL;
408         }
409
410         if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
411                 *access_mask = max_bits;
412                 return NT_STATUS_OK;
413         }
414
415         if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
416                 return NT_STATUS_PRIVILEGE_NOT_HELD;
417         }
418
419         if (*access_mask & ~max_bits) {
420                 return NT_STATUS_ACCESS_DENIED;
421         }
422
423         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
424
425         return NT_STATUS_OK;
426 }
427
428
429 /*
430   check the security descriptor on a file, if any
431   
432   *access_mask is modified with the access actually granted
433 */
434 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
435                            struct ntvfs_request *req,
436                            struct pvfs_filename *name,
437                            uint32_t *access_mask)
438 {
439         struct security_token *token = req->session_info->security_token;
440         struct xattr_NTACL *acl;
441         NTSTATUS status;
442         struct security_descriptor *sd;
443
444         if (pvfs_read_only(pvfs, *access_mask)) {
445                 return NT_STATUS_ACCESS_DENIED;
446         }
447
448         acl = talloc(req, struct xattr_NTACL);
449         if (acl == NULL) {
450                 return NT_STATUS_NO_MEMORY;
451         }
452
453         /* expand the generic access bits to file specific bits */
454         *access_mask = pvfs_translate_mask(*access_mask);
455         *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
456
457         status = pvfs_acl_load(pvfs, name, -1, acl);
458         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
459                 talloc_free(acl);
460                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
461         }
462         if (!NT_STATUS_IS_OK(status)) {
463                 return status;
464         }
465
466         switch (acl->version) {
467         case 1:
468                 sd = acl->info.sd;
469                 break;
470         default:
471                 return NT_STATUS_INVALID_ACL;
472         }
473
474         /* check the acl against the required access mask */
475         status = sec_access_check(sd, token, *access_mask, access_mask);
476
477         /* this bit is always granted, even if not asked for */
478         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
479
480         talloc_free(acl);
481         
482         return status;
483 }
484
485
486 /*
487   a simplified interface to access check, designed for calls that
488   do not take or return an access check mask
489 */
490 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
491                                   struct ntvfs_request *req,
492                                   struct pvfs_filename *name,
493                                   uint32_t access_needed)
494 {
495         if (access_needed == 0) {
496                 return NT_STATUS_OK;
497         }
498         return pvfs_access_check(pvfs, req, name, &access_needed);
499 }
500
501 /*
502   access check for creating a new file/directory
503 */
504 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
505                                   struct ntvfs_request *req,
506                                   struct pvfs_filename *name,
507                                   uint32_t *access_mask)
508 {
509         struct pvfs_filename *parent;
510         NTSTATUS status;
511
512         status = pvfs_resolve_parent(pvfs, req, name, &parent);
513         if (!NT_STATUS_IS_OK(status)) {
514                 return status;
515         }
516
517         status = pvfs_access_check(pvfs, req, parent, access_mask);
518         if (!NT_STATUS_IS_OK(status)) {
519                 return status;
520         }
521
522         if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
523                 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
524         }
525
526         return status;
527 }
528
529 /*
530   access check for creating a new file/directory - no access mask supplied
531 */
532 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs, 
533                                   struct ntvfs_request *req,
534                                   struct pvfs_filename *name,
535                                   uint32_t access_mask)
536 {
537         struct pvfs_filename *parent;
538         NTSTATUS status;
539
540         status = pvfs_resolve_parent(pvfs, req, name, &parent);
541         if (!NT_STATUS_IS_OK(status)) {
542                 return status;
543         }
544
545         return pvfs_access_check_simple(pvfs, req, parent, access_mask);
546 }
547
548
549 /*
550   determine if an ACE is inheritable
551 */
552 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
553                                  const struct security_ace *ace,
554                                  BOOL container)
555 {
556         if (!container) {
557                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
558         }
559
560         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
561                 return True;
562         }
563
564         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
565             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
566                 return True;
567         }
568
569         return False;
570 }
571
572 /*
573   this is the core of ACL inheritance. It copies any inheritable
574   aces from the parent SD to the child SD. Note that the algorithm 
575   depends on whether the child is a container or not
576 */
577 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
578                                       struct security_descriptor *parent_sd,
579                                       struct security_descriptor *sd,
580                                       BOOL container)
581 {
582         int i;
583         
584         for (i=0;i<parent_sd->dacl->num_aces;i++) {
585                 struct security_ace ace = parent_sd->dacl->aces[i];
586                 NTSTATUS status;
587                 const struct dom_sid *creator = NULL, *new_id = NULL;
588                 uint32_t orig_flags;
589
590                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
591                         continue;
592                 }
593
594                 orig_flags = ace.flags;
595
596                 /* see the RAW-ACLS inheritance test for details on these rules */
597                 if (!container) {
598                         ace.flags = 0;
599                 } else {
600                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
601
602                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
603                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
604                         }
605                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
606                                 ace.flags = 0;
607                         }
608                 }
609
610                 /* the CREATOR sids are special when inherited */
611                 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
612                         creator = pvfs->sid_cache.creator_owner;
613                         new_id = sd->owner_sid;
614                 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
615                         creator = pvfs->sid_cache.creator_group;
616                         new_id = sd->group_sid;
617                 } else {
618                         new_id = &ace.trustee;
619                 }
620
621                 if (creator && container && 
622                     (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
623                         uint32_t flags = ace.flags;
624
625                         ace.trustee = *new_id;
626                         ace.flags = 0;
627                         status = security_descriptor_dacl_add(sd, &ace);
628                         if (!NT_STATUS_IS_OK(status)) {
629                                 return status;
630                         }
631
632                         ace.trustee = *creator;
633                         ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
634                         status = security_descriptor_dacl_add(sd, &ace);
635                 } else if (container && 
636                            !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
637                         status = security_descriptor_dacl_add(sd, &ace);
638                 } else {
639                         ace.trustee = *new_id;
640                         status = security_descriptor_dacl_add(sd, &ace);
641                 }
642
643                 if (!NT_STATUS_IS_OK(status)) {
644                         return status;
645                 }
646         }
647
648         return NT_STATUS_OK;
649 }
650
651
652
653 /*
654   setup an ACL on a new file/directory based on the inherited ACL from
655   the parent. If there is no inherited ACL then we don't set anything,
656   as the default ACL applies anyway
657 */
658 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
659                           struct ntvfs_request *req,
660                           struct pvfs_filename *name,
661                           int fd)
662 {
663         struct xattr_NTACL *acl;
664         NTSTATUS status;
665         struct pvfs_filename *parent;
666         struct security_descriptor *parent_sd, *sd;
667         BOOL container;
668
669         /* form the parents path */
670         status = pvfs_resolve_parent(pvfs, req, name, &parent);
671         if (!NT_STATUS_IS_OK(status)) {
672                 return status;
673         }
674
675         acl = talloc(req, struct xattr_NTACL);
676         if (acl == NULL) {
677                 return NT_STATUS_NO_MEMORY;
678         }
679
680         status = pvfs_acl_load(pvfs, parent, -1, acl);
681         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
682                 return NT_STATUS_OK;
683         }
684         if (!NT_STATUS_IS_OK(status)) {
685                 return status;
686         }
687
688         switch (acl->version) {
689         case 1:
690                 parent_sd = acl->info.sd;
691                 break;
692         default:
693                 return NT_STATUS_INVALID_ACL;
694         }
695
696         if (parent_sd == NULL ||
697             parent_sd->dacl == NULL ||
698             parent_sd->dacl->num_aces == 0) {
699                 /* go with the default ACL */
700                 return NT_STATUS_OK;
701         }
702
703         /* create the new sd */
704         sd = security_descriptor_initialise(req);
705         if (sd == NULL) {
706                 return NT_STATUS_NO_MEMORY;
707         }
708
709         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
710         if (!NT_STATUS_IS_OK(status)) {
711                 return status;
712         }
713         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
714         if (!NT_STATUS_IS_OK(status)) {
715                 return status;
716         }
717
718         sd->type |= SEC_DESC_DACL_PRESENT;
719
720         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
721
722         /* fill in the aces from the parent */
723         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
724         if (!NT_STATUS_IS_OK(status)) {
725                 return status;
726         }
727
728         /* if there is nothing to inherit then we fallback to the
729            default acl */
730         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
731                 return NT_STATUS_OK;
732         }
733
734         acl->info.sd = sd;
735
736         status = pvfs_acl_save(pvfs, name, fd, acl);
737         
738         return status;
739 }