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